text: begin_unit
  comment|'# Copyright (c) 2011-2012 OpenStack Foundation'
  nl|'\n'
  comment|'# All Rights Reserved.'
  nl|'\n'
  comment|'#'
  nl|'\n'
  comment|'#    Licensed under the Apache License, Version 2.0 (the "License"); you may'
  nl|'\n'
  comment|'#    not use this file except in compliance with the License. You may obtain'
  nl|'\n'
  comment|'#    a copy of the License at'
  nl|'\n'
  comment|'#'
  nl|'\n'
  comment|'#         http://www.apache.org/licenses/LICENSE-2.0'
  nl|'\n'
  comment|'#'
  nl|'\n'
  comment|'#    Unless required by applicable law or agreed to in writing, software'
  nl|'\n'
  comment|'#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT'
  nl|'\n'
  comment|'#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the'
  nl|'\n'
  comment|'#    License for the specific language governing permissions and limitations'
  nl|'\n'
  comment|'#    under the License.'
  nl|'\n'
  nl|'\n'
  string|'"""\nGeneric Loadable class support.\n\nMeant to be used by such things as scheduler filters and weights where we\nwant to load modules from certain directories and find certain types of\nclasses within those modules.  Note that this is quite different than\ngeneric plugins and the pluginmanager code that exists elsewhere.\n\nUsage:\n\nCreate a directory with an __init__.py with code such as:\n\nclass SomeLoadableClass(object):\n    pass\n\n\nclass MyLoader(nova.loadables.BaseLoader)\n    def __init__(self):\n        super(MyLoader, self).__init__(SomeLoadableClass)\n\nIf you create modules in the same directory and subclass SomeLoadableClass\nwithin them, MyLoader().get_all_classes() will return a list\nof such classes.\n"""'
  newline|'\n'
  nl|'\n'
  name|'import'
  name|'inspect'
  newline|'\n'
  name|'import'
  name|'os'
  newline|'\n'
  name|'import'
  name|'sys'
  newline|'\n'
  nl|'\n'
  name|'from'
  name|'oslo_utils'
  name|'import'
  name|'importutils'
  newline|'\n'
  nl|'\n'
  name|'from'
  name|'nova'
  name|'import'
  name|'exception'
  newline|'\n'
  nl|'\n'
  nl|'\n'
  DECL|class|BaseLoader
  name|'class'
  name|'BaseLoader'
  op|'('
  name|'object'
  op|')'
  op|':'
  newline|'\n'
  DECL|member|__init__
  indent|'    '
  name|'def'
  name|'__init__'
  op|'('
  name|'self'
  op|','
  name|'loadable_cls_type'
  op|')'
  op|':'
  newline|'\n'
  indent|'        '
  name|'mod'
  op|'='
  name|'sys'
  op|'.'
  name|'modules'
  op|'['
  name|'self'
  op|'.'
  name|'__class__'
  op|'.'
  name|'__module__'
  op|']'
  newline|'\n'
  name|'self'
  op|'.'
  name|'path'
  op|'='
  name|'os'
  op|'.'
  name|'path'
  op|'.'
  name|'abspath'
  op|'('
  name|'mod'
  op|'.'
  name|'__path__'
  op|'['
  number|'0'
  op|']'
  op|')'
  newline|'\n'
  name|'self'
  op|'.'
  name|'package'
  op|'='
  name|'mod'
  op|'.'
  name|'__package__'
  newline|'\n'
  name|'self'
  op|'.'
  name|'loadable_cls_type'
  op|'='
  name|'loadable_cls_type'
  newline|'\n'
  nl|'\n'
  DECL|member|_is_correct_class
  dedent|''
  name|'def'
  name|'_is_correct_class'
  op|'('
  name|'self'
  op|','
  name|'obj'
  op|')'
  op|':'
  newline|'\n'
  indent|'        '
  string|'"""Return whether an object is a class of the correct type and\n        is not prefixed with an underscore.\n        """'
  newline|'\n'
  name|'return'
  op|'('
  name|'inspect'
  op|'.'
  name|'isclass'
  op|'('
  name|'obj'
  op|')'
  name|'and'
  nl|'\n'
  op|'('
  name|'not'
  name|'obj'
  op|'.'
  name|'__name__'
  op|'.'
  name|'startswith'
  op|'('
  string|"'_'"
  op|')'
  op|')'
  name|'and'
  nl|'\n'
  name|'issubclass'
  op|'('
  name|'obj'
  op|','
  name|'self'
  op|'.'
  name|'loadable_cls_type'
  op|')'
  op|')'
  newline|'\n'
  nl|'\n'
  DECL|member|_get_classes_from_module
  dedent|''
  name|'def'
  name|'_get_classes_from_module'
  op|'('
  name|'self'
  op|','
  name|'module_name'
  op|')'
  op|':'
  newline|'\n'
  indent|'        '
  string|'"""Get the classes from a module that match the type we want."""'
  newline|'\n'
  name|'classes'
  op|'='
  op|'['
  op|']'
  newline|'\n'
  name|'module'
  op|'='
  name|'importutils'
  op|'.'
  name|'import_module'
  op|'('
  name|'module_name'
  op|')'
  newline|'\n'
  name|'for'
  name|'obj_name'
  name|'in'
  name|'dir'
  op|'('
  name|'module'
  op|')'
  op|':'
  newline|'\n'
  comment|'# Skip objects that are meant to be private.'
  nl|'\n'
  indent|'            '
  name|'if'
  name|'obj_name'
  op|'.'
  name|'startswith'
  op|'('
  string|"'_'"
  op|')'
  op|':'
  newline|'\n'
  indent|'                '
  name|'continue'
  newline|'\n'
  dedent|''
  name|'itm'
  op|'='
  name|'getattr'
  op|'('
  name|'module'
  op|','
  name|'obj_name'
  op|')'
  newline|'\n'
  name|'if'
  name|'self'
  op|'.'
  name|'_is_correct_class'
  op|'('
  name|'itm'
  op|')'
  op|':'
  newline|'\n'
  indent|'                '
  name|'classes'
  op|'.'
  name|'append'
  op|'('
  name|'itm'
  op|')'
  newline|'\n'
  dedent|''
  dedent|''
  name|'return'
  name|'classes'
  newline|'\n'
  nl|'\n'
  DECL|member|get_all_classes
  dedent|''
  name|'def'
  name|'get_all_classes'
  op|'('
  name|'self'
  op|')'
  op|':'
  newline|'\n'
  indent|'        '
  string|'"""Get the classes of the type we want from all modules found\n        in the directory that defines this class.\n        """'
  newline|'\n'
  name|'classes'
  op|'='
  op|'['
  op|']'
  newline|'\n'
  name|'for'
  name|'dirpath'
  op|','
  name|'dirnames'
  op|','
  name|'filenames'
  name|'in'
  name|'os'
  op|'.'
  name|'walk'
  op|'('
  name|'self'
  op|'.'
  name|'path'
  op|')'
  op|':'
  newline|'\n'
  indent|'            '
  name|'relpath'
  op|'='
  name|'os'
  op|'.'
  name|'path'
  op|'.'
  name|'relpath'
  op|'('
  name|'dirpath'
  op|','
  name|'self'
  op|'.'
  name|'path'
  op|')'
  newline|'\n'
  name|'if'
  name|'relpath'
  op|'=='
  string|"'.'"
  op|':'
  newline|'\n'
  indent|'                '
  name|'relpkg'
  op|'='
  string|"''"
  newline|'\n'
  dedent|''
  name|'else'
  op|':'
  newline|'\n'
  indent|'                '
  name|'relpkg'
  op|'='
  string|"'.%s'"
  op|'%'
  string|"'.'"
  op|'.'
  name|'join'
  op|'('
  name|'relpath'
  op|'.'
  name|'split'
  op|'('
  name|'os'
  op|'.'
  name|'sep'
  op|')'
  op|')'
  newline|'\n'
  dedent|''
  name|'for'
  name|'fname'
  name|'in'
  name|'filenames'
  op|':'
  newline|'\n'
  indent|'                '
  name|'root'
  op|','
  name|'ext'
  op|'='
  name|'os'
  op|'.'
  name|'path'
  op|'.'
  name|'splitext'
  op|'('
  name|'fname'
  op|')'
  newline|'\n'
  name|'if'
  name|'ext'
  op|'!='
  string|"'.py'"
  name|'or'
  name|'root'
  op|'=='
  string|"'__init__'"
  op|':'
  newline|'\n'
  indent|'                    '
  name|'continue'
  newline|'\n'
  dedent|''
  name|'module_name'
  op|'='
  string|'"%s%s.%s"'
  op|'%'
  op|'('
  name|'self'
  op|'.'
  name|'package'
  op|','
  name|'relpkg'
  op|','
  name|'root'
  op|')'
  newline|'\n'
  name|'mod_classes'
  op|'='
  name|'self'
  op|'.'
  name|'_get_classes_from_module'
  op|'('
  name|'module_name'
  op|')'
  newline|'\n'
  name|'classes'
  op|'.'
  name|'extend'
  op|'('
  name|'mod_classes'
  op|')'
  newline|'\n'
  dedent|''
  dedent|''
  name|'return'
  name|'classes'
  newline|'\n'
  nl|'\n'
  DECL|member|get_matching_classes
  dedent|''
  name|'def'
  name|'get_matching_classes'
  op|'('
  name|'self'
  op|','
  name|'loadable_class_names'
  op|')'
  op|':'
  newline|'\n'
  indent|'        '
  string|'"""Get loadable classes from a list of names.  Each name can be\n        a full module path or the full path to a method that returns\n        classes to use.  The latter behavior is useful to specify a method\n        that returns a list of classes to use in a default case.\n        """'
  newline|'\n'
  name|'classes'
  op|'='
  op|'['
  op|']'
  newline|'\n'
  name|'for'
  name|'cls_name'
  name|'in'
  name|'loadable_class_names'
  op|':'
  newline|'\n'
  indent|'            '
  name|'obj'
  op|'='
  name|'importutils'
  op|'.'
  name|'import_class'
  op|'('
  name|'cls_name'
  op|')'
  newline|'\n'
  name|'if'
  name|'self'
  op|'.'
  name|'_is_correct_class'
  op|'('
  name|'obj'
  op|')'
  op|':'
  newline|'\n'
  indent|'                '
  name|'classes'
  op|'.'
  name|'append'
  op|'('
  name|'obj'
  op|')'
  newline|'\n'
  dedent|''
  name|'elif'
  name|'inspect'
  op|'.'
  name|'isfunction'
  op|'('
  name|'obj'
  op|')'
  op|':'
  newline|'\n'
  comment|'# Get list of classes from a function'
  nl|'\n'
  indent|'                '
  name|'for'
  name|'cls'
  name|'in'
  name|'obj'
  op|'('
  op|')'
  op|':'
  newline|'\n'
  indent|'                    '
  name|'classes'
  op|'.'
  name|'append'
  op|'('
  name|'cls'
  op|')'
  newline|'\n'
  dedent|''
  dedent|''
  name|'else'
  op|':'
  newline|'\n'
  indent|'                '
  name|'error_str'
  op|'='
  string|"'Not a class of the correct type'"
  newline|'\n'
  name|'raise'
  name|'exception'
  op|'.'
  name|'ClassNotFound'
  op|'('
  name|'class_name'
  op|'='
  name|'cls_name'
  op|','
  nl|'\n'
  name|'exception'
  op|'='
  name|'error_str'
  op|')'
  newline|'\n'
  dedent|''
  dedent|''
  name|'return'
  name|'classes'
  newline|'\n'
  dedent|''
  dedent|''
  endmarker|''
  end_unit
  