CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Classes | Functions | Variables
condformats_serialization_generate Namespace Reference

Classes

class  SerializationCodeGenerator
 

Functions

def get_basic_type_string
 
def get_default_gcc_search_paths
 
def get_diagnostics
 
def get_flags
 
def get_serializable_classes_members
 
def get_statement
 
def get_type_string
 
def is_definition_by_loc
 
def is_serializable_class
 
def is_serializable_class_manual
 
def log_flags
 
def main
 
def split_path
 

Variables

string __author__ = 'Miguel Ojeda'
 
string __copyright__ = 'Copyright 2014, CERN'
 
list __credits__ = ['Giacomo Govi', 'Miguel Ojeda', 'Andreas Pfeiffer']
 
string __email__ = 'mojedasa@cern.ch'
 
string __license__ = 'Unknown'
 
string __maintainer__ = 'Miguel Ojeda'
 
string headers_template
 
string instantiation_template
 
string serialize_method_base_object_template = ' ar & boost::serialization::make_nvp("{base_object_name}", boost::serialization::base_object<{base_object_name}>(*this));'
 
string serialize_method_begin_template
 
string serialize_method_end
 
string serialize_method_member_template = ''' ar & BOOST_SERIALIZATION_NVP({member_name});'''
 
tuple skip_namespaces
 

Function Documentation

def condformats_serialization_generate.get_basic_type_string (   node)

Definition at line 119 of file condformats_serialization_generate.py.

Referenced by get_type_string().

120 def get_basic_type_string(node):
121  typekinds = {
122  clang.cindex.TypeKind.BOOL: 'bool',
123  clang.cindex.TypeKind.INT: 'int',
124  clang.cindex.TypeKind.LONG: 'long',
125  clang.cindex.TypeKind.UINT: 'unsigned int',
126  clang.cindex.TypeKind.ULONG: 'unsigned long',
127  clang.cindex.TypeKind.FLOAT: 'float',
128  clang.cindex.TypeKind.DOUBLE: 'double',
129  }
130 
131  if node.type.kind not in typekinds:
132  raise Exception('Not a known basic type.')
133 
134  return typekinds[node.type.kind]
135 
def condformats_serialization_generate.get_default_gcc_search_paths (   gcc = 'g++',
  language = 'c++' 
)

Definition at line 357 of file condformats_serialization_generate.py.

358 def get_default_gcc_search_paths(gcc = 'g++', language = 'c++'):
359  command = 'echo "" | %s -x%s -v -E - 2>&1' % (gcc, language)
360  logging.debug('Running: %s', command)
361 
362  paths = []
363  in_list = False
364  for line in subprocess.check_output(command, shell=True).splitlines():
365  if in_list:
366  if line == 'End of search list.':
367  break
368 
369  path = os.path.normpath(line.strip())
370 
371  # Intrinsics not handled by clang
372  # Note that /lib/gcc is found in other paths if not normalized,
373  # so has to go after normpath()
374  if '/lib/gcc/' in path:
375  continue
376 
377  paths.append('-I%s' % path)
378 
379  else:
380  if line == '#include <...> search starts here:':
381  in_list = True
382 
383  if not in_list:
384  raise Exception('Default GCC search paths not found.')
385 
386  return paths
def condformats_serialization_generate.get_diagnostics (   translation_unit)

Definition at line 347 of file condformats_serialization_generate.py.

References python.multivaluedict.map().

348 def get_diagnostics(translation_unit):
349  return map(lambda diag: {
350  'severity' : diag.severity,
351  'location' : diag.location,
352  'spelling' : diag.spelling,
353  'ranges' : diag.ranges,
354  'fixits' : diag.fixits,
355  }, translation_unit.diagnostics)
356 
def condformats_serialization_generate.get_flags (   product_name,
  flags 
)

Definition at line 335 of file condformats_serialization_generate.py.

336 def get_flags(product_name, flags):
337  command = "scram b echo_%s_%s | tail -1 | cut -d '=' -f '2-' | xargs -n1" % (product_name, flags)
338  logging.debug('Running: %s', command)
339  return subprocess.check_output(command, shell=True).splitlines()
def condformats_serialization_generate.get_serializable_classes_members (   node,
  all_template_types = None,
  namespace = '',
  only_from_path = None 
)

Definition at line 144 of file condformats_serialization_generate.py.

References get_statement(), get_type_string(), is_definition_by_loc(), is_serializable_class(), is_serializable_class_manual(), and join().

145 def get_serializable_classes_members(node, all_template_types=None, namespace='', only_from_path=None):
146  if all_template_types is None:
147  all_template_types = []
148 
149  logging.debug('%s', (node.spelling, all_template_types, namespace))
150  results = {}
151  for child in node.get_children():
152  if child.kind == clang.cindex.CursorKind.NAMESPACE:
153  # If we are in the root namespace, let's skip some common, big
154  # namespaces to improve speed and avoid serializing those.
155  if namespace == '':
156  if child.spelling in skip_namespaces:
157  continue
158 
159  # This skips compiler-specific stuff as well (e.g. __gnucxx...)
160  if child.spelling.startswith('_'):
161  continue
162 
163  logging.debug('Going into namespace %s', child.spelling)
164 
165  results.update(get_serializable_classes_members(child, all_template_types, namespace + child.spelling + '::', only_from_path))
166  continue
167 
168  if child.kind in [clang.cindex.CursorKind.CLASS_DECL, clang.cindex.CursorKind.STRUCT_DECL, clang.cindex.CursorKind.CLASS_TEMPLATE] and is_definition_by_loc(child):
169  logging.debug('Found struct/class/template definition: %s', child.spelling if child.spelling else '<anonymous>')
170 
171  if only_from_path is not None \
172  and child.location.file is not None \
173  and not child.location.file.name.startswith(only_from_path):
174  logging.debug('Skipping since it is an external of this package: %s', child.spelling)
175  continue
176 
177  serializable = is_serializable_class(child)
178  if serializable:
179  if child.spelling == '':
180  raise Exception('It is not possible to serialize anonymous/unnamed structs/classes.')
181 
183  logging.info('Found manual serializable struct/class/template: %s', child.spelling)
184  continue
185 
186  logging.info('Found serializable struct/class/template: %s', child.spelling)
187 
188  template_types = []
189  base_objects = []
190  members = []
191  transients = []
192  after_serialize = False
193  after_serialize_count = 0
194  for member in child.get_children():
195  if after_serialize:
196  if after_serialize_count == 2:
197  after_serialize = False
198  else:
199  after_serialize_count = after_serialize_count + 1
200 
201  if member.kind != clang.cindex.CursorKind.UNEXPOSED_DECL:
202  raise Exception('Expected unexposed declaration (friend) after serialize() but found something else: looks like the COND_SERIALIZABLE macro has been changed without updating the script.')
203 
204  if 'COND_SERIALIZABLE' not in get_statement(member):
205  raise Exception('Could not find COND_SERIALIZABLE in the statement of the expected unexposed declarations (friends) after serialize(). Please fix the script/macro.')
206 
207  logging.debug('Skipping expected unexposed declaration (friend) after serialize().')
208  continue
209 
210  # Template type parameters (e.g. <typename T>)
211  if member.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER:
212  logging.info(' Found template type parameter: %s', member.spelling)
213  template_types.append(('typename', member.spelling))
214 
215  # Template non-type parameters (e.g. <int N>)
216  elif member.kind == clang.cindex.CursorKind.TEMPLATE_NON_TYPE_PARAMETER:
217  type_string = get_type_string(member)
218  logging.info(' Found template non-type parameter: %s %s', type_string, member.spelling)
219  template_types.append((type_string, member.spelling))
220 
221  # Base objects
222  elif member.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
223  # FIXME: .displayname gives sometimes things like "class mybase"
224  base_object = member.displayname
225  prefix = 'class '
226  if base_object.startswith(prefix):
227  base_object = base_object[len(prefix):]
228  logging.info(' Found base object: %s', base_object)
229  base_objects.append(base_object)
230 
231  # Member variables
232  elif member.kind == clang.cindex.CursorKind.FIELD_DECL and is_definition_by_loc(member):
233  # While clang 3.3 does not ignore unrecognized attributes
234  # (see http://llvm.org/viewvc/llvm-project?revision=165082&view=revision )
235  # for some reason they do not appear in the bindings yet
236  # so we just do it ourselves.
237 
238  # FIXME: To simplify and avoid parsing C++ ourselves, our transient
239  # attribute applies to *all* the variables declared in the same statement.
240  if 'COND_TRANSIENT' not in get_statement(member):
241  logging.info(' Found member variable: %s', member.spelling)
242  members.append(member.spelling)
243  else:
244  if serializable:
245  logging.info(' Found transient member variable: %s', member.spelling)
246  transients.append(member.spelling)
247  else:
248  raise Exception('Transient %s found for non-serializable class %s', member.spelling, child.spelling)
249 
250  elif member.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE and member.spelling == 'serialize':
251  after_serialize = True
252  logging.debug('Found serialize() method, skipping next two children which must be unexposed declarations.')
253 
254  elif member.kind in frozenset([
255  # For safety, we list all known kinds that we need to skip
256  # and raise in unknown cases (this helps catching problems
257  # with undefined classes)
258  clang.cindex.CursorKind.CONSTRUCTOR,
259  clang.cindex.CursorKind.DESTRUCTOR,
260  clang.cindex.CursorKind.CXX_METHOD,
261  clang.cindex.CursorKind.CXX_ACCESS_SPEC_DECL,
262  clang.cindex.CursorKind.FUNCTION_TEMPLATE,
263  clang.cindex.CursorKind.TYPEDEF_DECL,
264  clang.cindex.CursorKind.CLASS_DECL,
265  clang.cindex.CursorKind.ENUM_DECL,
266  clang.cindex.CursorKind.VAR_DECL,
267  clang.cindex.CursorKind.STRUCT_DECL,
268  clang.cindex.CursorKind.UNION_DECL,
269  clang.cindex.CursorKind.CONVERSION_FUNCTION,
270  clang.cindex.CursorKind.TYPE_REF,
271  clang.cindex.CursorKind.DECL_REF_EXPR,
272  ]):
273  logging.debug('Skipping member: %s %s %s %s', member.displayname, member.spelling, member.kind, member.type.kind)
274 
275  elif member.kind == clang.cindex.CursorKind.UNEXPOSED_DECL:
276  statement = get_statement(member)
277 
278  # Friends are unexposed but they are not data to serialize
279  if 'friend' in statement:
280  # If we know about them, skip the warning
281  if \
282  'friend class ' in statement or \
283  'friend struct ' in statement or \
284  'friend std::ostream& operator<<(' in statement or \
285  'friend std::istream& operator>>(' in statement:
286  logging.debug('Skipping known friend: %s', statement.splitlines()[0])
287  continue
288 
289  # Otherwise warn
290  logging.warning('Unexposed declaration that looks like a friend declaration -- please check: %s %s %s %s %s', member.displayname, member.spelling, member.kind, member.type.kind, statement)
291  continue
292 
293  raise Exception('Unexposed declaration. This probably means (at the time of writing) that an unknown class was found (may happen, for instance, when the compiler does not find the headers for std::vector, i.e. missing -I option): %s %s %s %s %s' % (member.displayname, member.spelling, member.kind, member.type.kind, statement))
294 
295  else:
296  raise Exception('Unknown kind. Please fix the script: %s %s %s %s %s' % (member.displayname, member.spelling, member.kind, member.type.kind, statement))
297 
298  if template_types:
299  template_use = '%s<%s>' % (child.spelling, ', '.join([template_type_name for (_, template_type_name) in template_types]))
300  else:
301  template_use = child.spelling
302 
303  new_namespace = namespace + template_use
304 
305  new_all_template_types = all_template_types + [template_types]
306 
307  results[new_namespace] = (child, serializable, new_all_template_types, base_objects, members, transients)
308 
309  results.update(get_serializable_classes_members(child, new_all_template_types, new_namespace + '::', only_from_path))
310 
311  for (klass, (node, serializable, all_template_types, base_objects, members, transients)) in results.items():
312  if serializable and len(members) == 0:
313  logging.info('No non-transient members found for serializable class %s', klass)
314 
315  return results
316 
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def condformats_serialization_generate.get_statement (   node)

Definition at line 102 of file condformats_serialization_generate.py.

Referenced by get_serializable_classes_members().

103 def get_statement(node):
104  # For some cursor kinds, their location is empty (e.g. translation units
105  # and attributes); either because of a bug or because they do not have
106  # a meaningful 'start' -- however, the extent is always available
107  if node.extent.start.file is None:
108  return None
109 
110  filename = node.extent.start.file.name
111  start = node.extent.start.offset
112  end = node.extent.end.offset
113 
114  with open(filename, 'rb') as fd:
115  source = fd.read()
116 
117  return source[start:source.find(';', end)]
118 
def condformats_serialization_generate.get_type_string (   node)

Definition at line 136 of file condformats_serialization_generate.py.

References get_basic_type_string().

Referenced by get_serializable_classes_members().

137 def get_type_string(node):
138  spelling = node.type.get_declaration().spelling
139  if spelling is not None:
140  return spelling
141 
142  return get_basic_type_string(node)
143 
def condformats_serialization_generate.is_definition_by_loc (   node)

Definition at line 70 of file condformats_serialization_generate.py.

Referenced by get_serializable_classes_members(), is_serializable_class(), and is_serializable_class_manual().

70 
71 def is_definition_by_loc(node):
72  if node.get_definition() is None:
73  return False
74  if node.location is None or node.get_definition().location is None:
75  return False
76  return node.location == node.get_definition().location
def condformats_serialization_generate.is_serializable_class (   node)

Definition at line 77 of file condformats_serialization_generate.py.

References is_definition_by_loc().

Referenced by get_serializable_classes_members().

77 
78 def is_serializable_class(node):
79  for child in node.get_children():
80  if child.spelling != 'serialize' or child.kind != clang.cindex.CursorKind.FUNCTION_TEMPLATE or is_definition_by_loc(child):
81  continue
82 
83  if [(x.spelling, x.kind, is_definition_by_loc(x), x.type.kind) for x in child.get_children()] != [
84  ('Archive', clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER, True, clang.cindex.TypeKind.UNEXPOSED),
85  ('ar', clang.cindex.CursorKind.PARM_DECL, True, clang.cindex.TypeKind.LVALUEREFERENCE),
86  ('version', clang.cindex.CursorKind.PARM_DECL, True, clang.cindex.TypeKind.UINT),
87  ]:
88  continue
89 
90  return True
91 
92  return False
93 
def condformats_serialization_generate.is_serializable_class_manual (   node)

Definition at line 94 of file condformats_serialization_generate.py.

References is_definition_by_loc().

Referenced by get_serializable_classes_members().

94 
96  for child in node.get_children():
97  if child.spelling == 'cond_serialization_manual' and child.kind == clang.cindex.CursorKind.CXX_METHOD and not is_definition_by_loc(child):
98  return True
99 
100  return False
101 
def condformats_serialization_generate.log_flags (   name,
  flags 
)

Definition at line 340 of file condformats_serialization_generate.py.

341 def log_flags(name, flags):
342  logging.debug('%s = [', name)
343  for flag in flags:
344  logging.debug(' %s', flag)
345  logging.debug(']')
346 
def condformats_serialization_generate.main ( )

Definition at line 525 of file condformats_serialization_generate.py.

References relval_generation_module.generate().

526 def main():
527  parser = argparse.ArgumentParser(description='CMS Condition DB Serialization generator.')
528  parser.add_argument('--verbose', '-v', action='count', help='Verbosity level. -v reports debugging information.')
529  parser.add_argument('--output' , '-o', action='store', help='Specifies the path to the output file written. Default: src/Serialization.cc')
530  parser.add_argument('--package', '-p', action='store', help='Specifies the path to the package to be processed. Default: the actual package')
531 
532  opts, args = parser.parse_known_args()
533 
534  logLevel = logging.INFO
535  if opts.verbose < 1 and opts.output and opts.package: # assume we're called by scram and reduce logging - but only if no verbose is requested
536  logLevel = logging.WARNING
537 
538  if opts.verbose >= 1:
539  logLevel = logging.DEBUG
540 
541  logging.basicConfig(
542  format = '[%(asctime)s] %(levelname)s: %(message)s',
543  level = logLevel,
544  )
545 
546  if opts.package: # we got a directory name to process, assume it's from scram and remove the last ('/src') dir from the path
547  pkgDir = opts.package
548  if pkgDir.endswith('/src') :
549  pkgDir, srcDir = os.path.split( opts.package )
550  os.chdir( pkgDir )
551  logging.info("Processing package in %s " % pkgDir)
552 
553  if opts.output:
554  logging.info("Writing serialization code to %s " % opts.output)
555 
556  SerializationCodeGenerator( scramFlags=args[1:] ).generate( opts.output )
def condformats_serialization_generate.split_path (   path)

Definition at line 317 of file condformats_serialization_generate.py.

Referenced by init_filter().

318 def split_path(path):
319  folders = []
320 
321  while True:
322  path, folder = os.path.split(path)
323 
324  if folder != '':
325  folders.append(folder)
326  else:
327  if path != '':
328  folders.append(path)
329  break
330 
331  folders.reverse()
332 
333  return folders
334 

Variable Documentation

string condformats_serialization_generate.__author__ = 'Miguel Ojeda'

Definition at line 16 of file condformats_serialization_generate.py.

string condformats_serialization_generate.__copyright__ = 'Copyright 2014, CERN'

Definition at line 17 of file condformats_serialization_generate.py.

list condformats_serialization_generate.__credits__ = ['Giacomo Govi', 'Miguel Ojeda', 'Andreas Pfeiffer']

Definition at line 18 of file condformats_serialization_generate.py.

string condformats_serialization_generate.__email__ = 'mojedasa@cern.ch'

Definition at line 21 of file condformats_serialization_generate.py.

string condformats_serialization_generate.__license__ = 'Unknown'

Definition at line 19 of file condformats_serialization_generate.py.

string condformats_serialization_generate.__maintainer__ = 'Miguel Ojeda'

Definition at line 20 of file condformats_serialization_generate.py.

string condformats_serialization_generate.headers_template
Initial value:
1 = '''
2 #include "{headers}"
3 
4 #include <boost/serialization/base_object.hpp>
5 #include <boost/serialization/nvp.hpp>
6 #include <boost/serialization/export.hpp>
7 
8 #include "CondFormats/Serialization/interface/Equal.h"
9 #include "CondFormats/Serialization/interface/Instantiate.h"
10 
11 '''

Definition at line 32 of file condformats_serialization_generate.py.

string condformats_serialization_generate.instantiation_template
Initial value:
1 = '''COND_SERIALIZATION_INSTANTIATE({klass});
2 '''

Definition at line 55 of file condformats_serialization_generate.py.

string condformats_serialization_generate.serialize_method_base_object_template = ' ar & boost::serialization::make_nvp("{base_object_name}", boost::serialization::base_object<{base_object_name}>(*this));'

Definition at line 48 of file condformats_serialization_generate.py.

string condformats_serialization_generate.serialize_method_begin_template
Initial value:
1 = '''template <class Archive>
2 void {klass}::serialize(Archive & ar, const unsigned int)
3 {{'''

Definition at line 44 of file condformats_serialization_generate.py.

string condformats_serialization_generate.serialize_method_end
Initial value:
1 = '''}
2 '''

Definition at line 52 of file condformats_serialization_generate.py.

string condformats_serialization_generate.serialize_method_member_template = ''' ar & BOOST_SERIALIZATION_NVP({member_name});'''

Definition at line 50 of file condformats_serialization_generate.py.

tuple condformats_serialization_generate.skip_namespaces
Initial value:
1 = frozenset([
2  # Do not go inside anonymous namespaces (static)
3  '',
4 
5  # Do not go inside some standard namespaces
6  'std', 'boost', 'mpl_', 'boost_swap_impl',
7 
8  # Do not go inside some big namespaces coming from externals
9  'ROOT', 'edm', 'ora', 'coral', 'CLHEP', 'Geom', 'HepGeom',
10 ])

Definition at line 59 of file condformats_serialization_generate.py.