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_serializable_classes_members(), and 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 359 of file condformats_serialization_generate.py.

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

Definition at line 349 of file condformats_serialization_generate.py.

References python.multivaluedict.map().

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

Definition at line 337 of file condformats_serialization_generate.py.

338 def get_flags(product_name, flags):
339  command = "scram b echo_%s_%s | tail -1 | cut -d '=' -f '2-' | xargs -n1" % (product_name, flags)
340  logging.debug('Running: %s', command)
341  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_basic_type_string(), 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  if not type_string:
219  type_string = get_basic_type_string(member)
220  logging.info(' Found template non-type parameter: %s %s', type_string, member.spelling)
221  template_types.append((type_string, member.spelling))
222 
223  # Base objects
224  elif member.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
225  # FIXME: .displayname gives sometimes things like "class mybase"
226  base_object = member.displayname
227  prefix = 'class '
228  if base_object.startswith(prefix):
229  base_object = base_object[len(prefix):]
230  logging.info(' Found base object: %s', base_object)
231  base_objects.append(base_object)
232 
233  # Member variables
234  elif member.kind == clang.cindex.CursorKind.FIELD_DECL and is_definition_by_loc(member):
235  # While clang 3.3 does not ignore unrecognized attributes
236  # (see http://llvm.org/viewvc/llvm-project?revision=165082&view=revision )
237  # for some reason they do not appear in the bindings yet
238  # so we just do it ourselves.
239 
240  # FIXME: To simplify and avoid parsing C++ ourselves, our transient
241  # attribute applies to *all* the variables declared in the same statement.
242  if 'COND_TRANSIENT' not in get_statement(member):
243  logging.info(' Found member variable: %s', member.spelling)
244  members.append(member.spelling)
245  else:
246  if serializable:
247  logging.info(' Found transient member variable: %s', member.spelling)
248  transients.append(member.spelling)
249  else:
250  raise Exception('Transient %s found for non-serializable class %s', member.spelling, child.spelling)
251 
252  elif member.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE and member.spelling == 'serialize':
253  after_serialize = True
254  logging.debug('Found serialize() method, skipping next two children which must be unexposed declarations.')
255 
256  elif member.kind in frozenset([
257  # For safety, we list all known kinds that we need to skip
258  # and raise in unknown cases (this helps catching problems
259  # with undefined classes)
260  clang.cindex.CursorKind.CONSTRUCTOR,
261  clang.cindex.CursorKind.DESTRUCTOR,
262  clang.cindex.CursorKind.CXX_METHOD,
263  clang.cindex.CursorKind.CXX_ACCESS_SPEC_DECL,
264  clang.cindex.CursorKind.FUNCTION_TEMPLATE,
265  clang.cindex.CursorKind.TYPEDEF_DECL,
266  clang.cindex.CursorKind.CLASS_DECL,
267  clang.cindex.CursorKind.ENUM_DECL,
268  clang.cindex.CursorKind.VAR_DECL,
269  clang.cindex.CursorKind.STRUCT_DECL,
270  clang.cindex.CursorKind.UNION_DECL,
271  clang.cindex.CursorKind.CONVERSION_FUNCTION,
272  clang.cindex.CursorKind.TYPE_REF,
273  clang.cindex.CursorKind.DECL_REF_EXPR,
274  ]):
275  logging.debug('Skipping member: %s %s %s %s', member.displayname, member.spelling, member.kind, member.type.kind)
276 
277  elif member.kind == clang.cindex.CursorKind.UNEXPOSED_DECL:
278  statement = get_statement(member)
279 
280  # Friends are unexposed but they are not data to serialize
281  if 'friend' in statement:
282  # If we know about them, skip the warning
283  if \
284  'friend class ' in statement or \
285  'friend struct ' in statement or \
286  'friend std::ostream& operator<<(' in statement or \
287  'friend std::istream& operator>>(' in statement:
288  logging.debug('Skipping known friend: %s', statement.splitlines()[0])
289  continue
290 
291  # Otherwise warn
292  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)
293  continue
294 
295  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))
296 
297  else:
298  raise Exception('Unknown kind. Please fix the script: %s %s %s %s %s' % (member.displayname, member.spelling, member.kind, member.type.kind, statement))
299 
300  if template_types:
301  template_use = '%s<%s>' % (child.spelling, ', '.join([template_type_name for (_, template_type_name) in template_types]))
302  else:
303  template_use = child.spelling
304 
305  new_namespace = namespace + template_use
306 
307  new_all_template_types = all_template_types + [template_types]
308 
309  results[new_namespace] = (child, serializable, new_all_template_types, base_objects, members, transients)
310 
311  results.update(get_serializable_classes_members(child, new_all_template_types, new_namespace + '::', only_from_path))
312 
313  for (klass, (node, serializable, all_template_types, base_objects, members, transients)) in results.items():
314  if serializable and len(members) == 0:
315  logging.info('No non-transient members found for serializable class %s', klass)
316 
317  return results
318 
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 342 of file condformats_serialization_generate.py.

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

Definition at line 527 of file condformats_serialization_generate.py.

References relval_generation_module.generate().

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

Definition at line 319 of file condformats_serialization_generate.py.

Referenced by init_filter().

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

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.