class Plugin(PluginBase): # ---------------------------------------------------------------------- # | Public Properties Name = DerivedProperty("Pickle") Description = DerivedProperty("Pickles each element to a file") Flags = DerivedProperty(ParseFlag.AllFlags) # ---------------------------------------------------------------------- # | Public Methods @staticmethod @override def IsValidEnvironment(): return True # ---------------------------------------------------------------------- @staticmethod @override def GenerateCustomSettingsAndDefaults(): return [] # ---------------------------------------------------------------------- @staticmethod @override def GenerateOutputFilenames(context): # Return a single item (that will never be used), as an empty lists # aren't supported. return [ "{}.{}".format(context["output_name"], ext) for ext in ["pickle", "path"] ] # ---------------------------------------------------------------------- @staticmethod @override def Generate(simple_schema_generator, invoke_reason, input_filenames, output_filenames, name, elements, include_indexes, status_stream, verbose_stream, verbose, **custom_settings): assert len(output_filenames) == 2, output_filenames # Pickle status_stream.write("Creating '{}'...".format(output_filenames[0])) with status_stream.DoneManager() as status_dm: with open(output_filenames[0], "wb") as f: pickle.dump(elements, f) # Path status_stream.write("Creating '{}'...".format(output_filenames[1])) with status_stream.DoneManager() as status_dm: generator_path = os.path.dirname( simple_schema_generator.OriginalModuleFilename) assert os.path.isdir(generator_path), generator_path generator_path = os.path.dirname(generator_path) with open(output_filenames[1], "w") as f: f.write(generator_path)
class _PlaceholderTypeInfo(TypeInfo): Desc = DerivedProperty("") ConstraintsDesc = DerivedProperty("") ExpectedType = bool @staticmethod @override def _ValidateItemNoThrowImpl(item): # <Parameters differ from overridden...> pylint: disable = W0221 pass
class Plugin(PluginBase): # ---------------------------------------------------------------------- # | Public Properties Name = DerivedProperty("Debug") Description = DerivedProperty("Displays diagnostic information about each element") Flags = DerivedProperty(ParseFlag.AllFlags) # ---------------------------------------------------------------------- # | Public Methods @staticmethod @override def IsValidEnvironment(): return True # ---------------------------------------------------------------------- @staticmethod @override def GenerateCustomSettingsAndDefaults(): return [] # ---------------------------------------------------------------------- @staticmethod @override def GenerateOutputFilenames(context): # Return a single item (that will never be used), as an empty lists # aren't supported. return ["placeholder"] # ---------------------------------------------------------------------- @staticmethod @override def Generate( simple_schema_generator, invoke_reason, input_filenames, output_filenames, name, elements, include_indexes, status_stream, verbose_stream, verbose, **custom_settings ): # ---------------------------------------------------------------------- def Impl(element): status_stream.write(str(element)) status_stream.write("\n\n") # ---------------------------------------------------------------------- for include_index in include_indexes: Impl(elements[include_index])
class CodeGenerator( AtomicInputProcessingMixin, ConditionalInvocationQueryMixin, MultipleOutputMixin, CodeGeneratorMod.CodeGenerator, ): # ---------------------------------------------------------------------- # | # | Public Properties # | # ---------------------------------------------------------------------- Name = DerivedProperty(name) Description = DerivedProperty(description) InputTypeInfo = DerivedProperty( FilenameTypeInfo( validation_expression=filename_validation_expression)) OriginalModuleFilename = calling_mod_filename RequiresOutputName = requires_output_name # ---------------------------------------------------------------------- # | # | Public Methods # | # ---------------------------------------------------------------------- @staticmethod @override def IsSupportedContent(filename): return is_supported_content_func is None or is_supported_content_func( filename) # ---------------------------------------------------------------------- # | # | Protected Methods # | # ---------------------------------------------------------------------- @classmethod @override def _GetOptionalMetadata(cls): return get_optional_metadata_func() + \ [ ( "plugin_settings", {} ), ] + \ super(CodeGenerator, cls)._GetOptionalMetadata() # ---------------------------------------------------------------------- @classmethod @override def _GetRequiredMetadataNames(cls): names = [ "plugin_name", ] if cls.RequiresOutputName: names += [ "output_name", ] names += super(CodeGenerator, cls)._GetRequiredMetadataNames() return names # ---------------------------------------------------------------------- @classmethod @override def _CreateContext(cls, metadata, status_stream): if metadata["plugin_name"] not in plugin_map: raise CommandLine.UsageException( "'{}' is not a valid plugin".format( metadata["plugin_name"])) plugin = plugin_map[metadata["plugin_name"]].Plugin # Ensure that all plugin settings are present and that they # are the expected type. custom_settings = OrderedDict([ (k, v) for k, v in plugin.GenerateCustomSettingsAndDefaults() ]) plugin_settings = metadata["plugin_settings"] for k, v in six.iteritems(plugin_settings): if k not in custom_settings: raise CommandLine.UsageException( "'{}' is not a valid plugin setting".format(k)) desired_type = type(custom_settings[k]) if type(v) != desired_type: assert isinstance(v, (str, UnicodeDecodeError)), (v, type(v)) plugin_settings[k] = StringSerialization.DeserializeItem( CreateFromPythonType(desired_type), v) for k, v in six.iteritems(custom_settings): if k not in plugin_settings: plugin_settings[k] = v metadata["plugin_settings"] = plugin.PreprocessMetadata( plugin_settings) # Invoke custom functionality context = create_context_func(metadata, plugin) context = plugin.PreprocessContext(context) context["output_filenames"] = [ os.path.join(context["output_dir"], filename) for filename in plugin.GenerateOutputFilenames(context) ] context = plugin.PostprocessContext(context) if postprocess_context_func: context = postprocess_context_func(context, plugin) return super(CodeGenerator, cls)._CreateContext(context, status_stream) # ---------------------------------------------------------------------- @classmethod @override def _InvokeImpl( cls, invoke_reason, context, status_stream, verbose_stream, verbose, ): return invoke_func( cls, invoke_reason, context, status_stream, verbose_stream, verbose, plugin_map[context["plugin_name"]].Plugin, ) # ---------------------------------------------------------------------- @classmethod @override def _GetAdditionalGeneratorItems(cls, context): # ---------------------------------------------------------------------- def ProcessorGeneratorItem(item): if isinstance(item, six.string_types) and item in plugin_map: return plugin_map[item].Plugin return item # ---------------------------------------------------------------------- plugin = plugin_map[context["plugin_name"]].Plugin return [ cls, cls.OriginalModuleFilename, plugin, ] + \ list(plugin.GetAdditionalGeneratorItems(context)) + \ super(CodeGenerator, cls)._GetAdditionalGeneratorItems(context)
class Plugin(PluginBase): # ---------------------------------------------------------------------- # | Public Properties Name = DerivedProperty("Dot") Description = DerivedProperty( "Generates a DOT file that contains all elements (https://en.wikipedia.org/wiki/DOT_(graph_description_language))" ) Flags = DerivedProperty(ParseFlag.AllFlags) # ---------------------------------------------------------------------- # | Public Methods @staticmethod @override def IsValidEnvironment(): return True # ---------------------------------------------------------------------- @staticmethod @override def GenerateCustomSettingsAndDefaults(): yield "no_attributes", False # ---------------------------------------------------------------------- @staticmethod @override def GenerateOutputFilenames(context): return [ os.path.join(context["output_dir"], "{}.gv".format(context["output_name"])) ] # ---------------------------------------------------------------------- @staticmethod @override def Generate( simple_schema_generator, invoke_reason, input_filenames, output_filenames, name, elements, include_indexes, status_stream, verbose_stream, verbose, no_attributes, ): assert len(output_filenames) == 1, output_filenames output_filename = output_filenames[0] common_input_prefix = FileSystem.GetCommonPath(*input_filenames) with open(output_filename, "w") as f: f.write( textwrap.dedent( """\ digraph g { graph [ rankdir = "LR" ]; """, ), ) indented_stream = StreamDecorator( f, line_prefix=" ", ) # ---------------------------------------------------------------------- def Impl(element): if element.IsDefinitionOnly: element_type = "Definition" style = "dashed" elif getattr(element, "IsAttribute", False): element_type = "Attribute" style = "rounded" else: element_type = "Standard" style = None type_info_type = element.TypeInfo.__class__.__name__ indented_stream.write( textwrap.dedent( """\ "{dotted}" [ shape = rectangle {style} label = < <table border="0"> <tr> <td align="left"><b>{name}</b></td> <td align="right">{element_type}<br align="right"/>{type_info}</td> </tr> <hr/> <tr> <td colspan="2">{source} [{line}:{column}]</td> </tr> <hr/> <tr> <td align="left">Arity:</td> <td align="right">{arity}</td> </tr> """, ).format( dotted=element.DottedName, name=element.Name, style="style = {}".format(style) if style else "", element_type=element_type, type_info=type_info_type, source=FileSystem.TrimPath(element.Source, common_input_prefix), line=element.Line, column=element.Column, arity=element.TypeInfo.Arity.ToString() or "1", ), ) if type_info_type != "ClassTypeInfo": indented_stream.write( StringHelpers.LeftJustify( textwrap.dedent( """\ <tr> <td align="left">Constraints:</td> <td align="right">{}</td> </tr> """, ).format( html.escape( element.TypeInfo.ConstraintsDesc), ), 8, skip_first_line=False, ), ) if not no_attributes: table_rows = [] for key, metadata_value in six.iteritems( element.Metadata.Values): table_rows.append( textwrap.dedent( """\ <tr> <td align="left">{}:</td> <td align="right">{}</td> </tr> """, ).format( html.escape(key), html.escape(metadata_value.Value), ), ) if table_rows: indented_stream.write( StringHelpers.LeftJustify( textwrap.dedent( """\ <hr/> {} """, ).format("".join(table_rows)), 8, skip_first_line=False, ), ) indented_stream.write( textwrap.dedent( """\ </table> > ]; """, ), ) for child in getattr(element, "Children", []): Impl(child) indented_stream.write('"{}":f0 -> "{}":f0\n'.format( element.DottedName, child.DottedName)) # ---------------------------------------------------------------------- for element in elements: Impl(element) f.write("}\n")
class Plugin(PluginBase): # ---------------------------------------------------------------------- # | Public Properties Name = DerivedProperty("PyDictionary") Description = DerivedProperty( "Generates python source code that contains a dictionary with top-level enum schema elements that have corresponding friendly names" ) Flags = DerivedProperty(ParseFlag.AllFlags) # ---------------------------------------------------------------------- # | Public Methods @staticmethod @override def IsValidEnvironment(): return True # ---------------------------------------------------------------------- @staticmethod @override def GenerateCustomSettingsAndDefaults(): return [] # ---------------------------------------------------------------------- @staticmethod @override def GenerateOutputFilenames(context): return ["{}_dict.py".format(context["output_name"])] # ---------------------------------------------------------------------- @classmethod @override def Generate(cls, simple_schema_generator, invoke_reason, input_filenames, output_filenames, name, elements, include_indexes, status_stream, verbose_stream, verbose, **custom_settings): assert len(output_filenames) == 1, output_filenames output_filename = output_filenames[0] del output_filenames status_stream.write("Creating '{}'...".format(output_filename)) with status_stream.DoneManager() as this_dm: with open(output_filename, "w") as f: f.write( textwrap.dedent( """\ {} from collections import OrderedDict """, ).format( cls._GenerateFileHeader( prefix="# ", filename_prefix="<SimpleSchemaGenerator>/", ), ), ) nonlocals = CommonEnvironment.Nonlocals(wrote_value=False, ) # ---------------------------------------------------------------------- def OnCompoundVisitingChildren( element, *args, **kwargs): # <Unused argument> pylint: disable = W0613 # Don't visit children return False # ---------------------------------------------------------------------- def OnSimpleVisitingChildren( element, *args, **kwargs): # <Unused argument> pylint: disable = W0613 # Don't visit children return False # ---------------------------------------------------------------------- def OnFundamental( element, *args, **kwargs): # <Unused argument> pylint: disable = W0613 if not isinstance(element.TypeInfo, EnumTypeInfo): return if not element.TypeInfo.FriendlyValues: return name = element.Name reversed_name = "{}_reversed".format(name) prefix = "{} = OrderedDict".format(name) reversed_prefix = "{} = OrderedDict".format(reversed_name) f.write( textwrap.dedent( """\ {prefix}{assignments} {name}_max_key_length = len(max({name}.keys(), len)) {name}_max_value_length = len(max({name}.values(), len)) {reversed_prefix}{reversed_assignments} {reversed_name}_max_key_length = len(max({reversed_name}.keys(), len)) {reversed_name}_max_value_length = len(max({reversed_name}.values(), len)) """, ).format( prefix=prefix, assignments=StringHelpers.LeftJustify( "([ {}\n ])".format( "\n ".join([ '( "{}", "{}" ),'.format(v, fv) for v, fv in six.moves.zip( element.TypeInfo.Values, element.TypeInfo.FriendlyValues) ]), ), len(prefix), ), name=name, reversed_prefix=reversed_prefix, reversed_assignments=StringHelpers.LeftJustify( "([ {}\n ])".format( "\n ".join([ '( "{}", "{}" ),'.format(fv, v) for v, fv in six.moves.zip( element.TypeInfo.Values, element.TypeInfo.FriendlyValues) ]), ), len(reversed_prefix), ), reversed_name=reversed_name, ), ) nonlocals.wrote_value = True # ---------------------------------------------------------------------- simple_element_visitor = Elements.CreateElementVisitor( on_fundamental_func=OnFundamental, on_compound_visiting_children_func= OnCompoundVisitingChildren, on_simple_visiting_children_func=OnSimpleVisitingChildren, ) for include_index in include_indexes: element = elements[include_index] simple_element_visitor.Accept(element) if not nonlocals.wrote_value: f.write( "# No enum values with friendly names were found.\n")