Example #1
0
def expand_file_path_name_posix(fpn, dir_path=''):
    """ Expand environment variables in fpn to get filePathName.
    - if it is an absolute path return filePathName else
    - if it still has a local file path prepend dir_path to the filePathName and return dir_path + filePathName.
    """
    filePathName = posixpath.expandvars(
        fpn)  # support using environment variables in the file path
    filePathName = filePathName.replace('\\', '/')
    if os.path.isabs(filePathName):
        return posixpath.normpath(filePathName)  # use absolute path to file
    else:
        return posixpath.join(
            posixpath.expandvars(dir_path.replace('\\', '/')), filePathName
        )  # derive path to file from the directory path and a directory path to the file
Example #2
0
 def __call__(cls, *args):
     if args:
         value = posixpath.expandvars(
             posixpath.expanduser(
                 posixpath.join(*args)))
     else:
         value = str()
     return value
Example #3
0
 def __call__(cls, *args, **kwargs):
     if args:
         value = posixpath.expandvars(
             posixpath.expanduser(
                 posixpath.join(*args)))
     else:
         value = str()
     if value and 'obj' in kwargs or 'object' in kwargs:
         value = pathlib.Path(value)
     return value
Example #4
0
 def test_expandvars_nonascii_word(self):
     encoding = sys.getfilesystemencoding()
     uwnonascii = test_support.FS_NONASCII
     swnonascii = uwnonascii.encode(encoding)
     if not swnonascii:
         self.skipTest('Needs non-ASCII word characters')
     with test_support.EnvironmentVarGuard() as env:
         env.clear()
         env[swnonascii] = 'baz' + swnonascii
         self.assertEqual(posixpath.expandvars(u'$%s bar' % uwnonascii),
                          u'baz%s bar' % uwnonascii)
Example #5
0
 def test_expandvars_nonascii_word(self):
     encoding = sys.getfilesystemencoding()
     # Non-ASCII word characters
     letters = test_support.u(r'\xe6\u0130\u0141\u03c6\u041a\u05d0\u062a\u0e01')
     uwnonascii = letters.encode(encoding, 'ignore').decode(encoding)[:3]
     swnonascii = uwnonascii.encode(encoding)
     if not swnonascii:
         self.skipTest('Needs non-ASCII word characters')
     with test_support.EnvironmentVarGuard() as env:
         env.clear()
         env[swnonascii] = 'baz' + swnonascii
         self.assertEqual(posixpath.expandvars(u'$%s bar' % uwnonascii),
                          u'baz%s bar' % uwnonascii)
Example #6
0
    def test_expandvars(self):
        oldenv = os.environ.copy()
        try:
            os.environ.clear()
            os.environ["foo"] = "bar"
            os.environ["{foo"] = "baz1"
            os.environ["{foo}"] = "baz2"
            self.assertEqual(posixpath.expandvars("foo"), "foo")
            self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar")
            self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar")
            self.assertEqual(posixpath.expandvars("$?bar"), "$?bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar")
            self.assertEqual(posixpath.expandvars("${foo"), "${foo")
            self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}")
        finally:
            os.environ.clear()
            os.environ.update(oldenv)

        self.assertRaises(TypeError, posixpath.expandvars)
Example #7
0
    def test_expandvars(self):
        oldenv = os.environ.copy()
        try:
            os.environ.clear()
            os.environ["foo"] = "bar"
            os.environ["{foo"] = "baz1"
            os.environ["{foo}"] = "baz2"
            self.assertEqual(posixpath.expandvars("foo"), "foo")
            self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar")
            self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar")
            self.assertEqual(posixpath.expandvars("$?bar"), "$?bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar")
            self.assertEqual(posixpath.expandvars("${foo"), "${foo")
            self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}")
        finally:
            os.environ.clear()
            os.environ.update(oldenv)

        self.assertRaises(TypeError, posixpath.expandvars)
Example #8
0
 def test_expandvars_nonascii_word(self):
     encoding = sys.getfilesystemencoding()
     # Non-ASCII word characters
     letters = test_support.u(r'\xe6\u0130\u0141\u03c6\u041a\u05d0\u062a\u0e01')
     uwnonascii = letters.encode(encoding, 'ignore').decode(encoding)[:3]
     swnonascii = uwnonascii.encode(encoding)
     if not swnonascii:
         self.skipTest('Needs non-ASCII word characters')
     with test_support.EnvironmentVarGuard() as env:
         env.clear()
         env[swnonascii] = 'baz' + swnonascii
         self.assertEqual(posixpath.expandvars(u'$%s bar' % uwnonascii),
                          u'baz%s bar' % uwnonascii)
Example #9
0
    def test_expandvars(self):
        with support.EnvironmentVarGuard() as env:
            env.clear()
            env["foo"] = "bar"
            env["{foo"] = "baz1"
            env["{foo}"] = "baz2"
            self.assertEqual(posixpath.expandvars("foo"), "foo")
            self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar")
            self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar")
            self.assertEqual(posixpath.expandvars("$?bar"), "$?bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar")
            self.assertEqual(posixpath.expandvars("${foo"), "${foo")
            self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}")
            self.assertEqual(posixpath.expandvars("$foo$foo"), "barbar")
            self.assertEqual(posixpath.expandvars("$bar$bar"), "$bar$bar")

            self.assertEqual(posixpath.expandvars(b"foo"), b"foo")
            self.assertEqual(posixpath.expandvars(b"$foo bar"), b"bar bar")
            self.assertEqual(posixpath.expandvars(b"${foo}bar"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$[foo]bar"), b"$[foo]bar")
            self.assertEqual(posixpath.expandvars(b"$bar bar"), b"$bar bar")
            self.assertEqual(posixpath.expandvars(b"$?bar"), b"$?bar")
            self.assertEqual(posixpath.expandvars(b"${foo}bar"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$foo}bar"), b"bar}bar")
            self.assertEqual(posixpath.expandvars(b"${foo"), b"${foo")
            self.assertEqual(posixpath.expandvars(b"${{foo}}"), b"baz1}")
            self.assertEqual(posixpath.expandvars(b"$foo$foo"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$bar$bar"), b"$bar$bar")
            self.assertRaises(TypeError, posixpath.expandvars)
    def test_expandvars(self):
        with support.EnvironmentVarGuard() as env:
            env.clear()
            env["foo"] = "bar"
            env["{foo"] = "baz1"
            env["{foo}"] = "baz2"
            self.assertEqual(posixpath.expandvars("foo"), "foo")
            self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar")
            self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar")
            self.assertEqual(posixpath.expandvars("$?bar"), "$?bar")
            self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
            self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar")
            self.assertEqual(posixpath.expandvars("${foo"), "${foo")
            self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}")
            self.assertEqual(posixpath.expandvars("$foo$foo"), "barbar")
            self.assertEqual(posixpath.expandvars("$bar$bar"), "$bar$bar")

            self.assertEqual(posixpath.expandvars(b"foo"), b"foo")
            self.assertEqual(posixpath.expandvars(b"$foo bar"), b"bar bar")
            self.assertEqual(posixpath.expandvars(b"${foo}bar"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$[foo]bar"), b"$[foo]bar")
            self.assertEqual(posixpath.expandvars(b"$bar bar"), b"$bar bar")
            self.assertEqual(posixpath.expandvars(b"$?bar"), b"$?bar")
            self.assertEqual(posixpath.expandvars(b"${foo}bar"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$foo}bar"), b"bar}bar")
            self.assertEqual(posixpath.expandvars(b"${foo"), b"${foo")
            self.assertEqual(posixpath.expandvars(b"${{foo}}"), b"baz1}")
            self.assertEqual(posixpath.expandvars(b"$foo$foo"), b"barbar")
            self.assertEqual(posixpath.expandvars(b"$bar$bar"), b"$bar$bar")
            self.assertRaises(TypeError, posixpath.expandvars)
Example #11
0
def runme():

    #
    # Path of the pythondoc or pydoc.py script
    #
    pydoc_path = find_pydoc_path()
    if not pydoc_path:
        sys.stderr.write("unable to locate pydoc script\n")
        quit()
    sys.stderr.write("pydoc was found in\n" + pydoc_path + "\n")

    #
    # Get names of py files to document
    #
    #    glob_pattern = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Mediator' + os.sep + '*.py')
    glob_pattern = posixpath.expandvars('$VCODE_HOME' + os.sep + '*' + os.sep +
                                        '*.py')
    files = glob.glob(glob_pattern)

    #
    # Remove files that don't match name patter
    #
    slow = 0
    if sys.argv:
        opts, args = util.gopt(['s', None])
        # parse command line options and arguments
        if opts:
            if opts['s']:
                slow = 1
        regs_file_name = args
    if regs_file_name:
        orig_files = files
        files = []
        for a_file in orig_files:
            for a_reg in regs_file_name:
                a_reg = '[\s\S]*\\' + os.sep + a_reg + '$'
                if re.match(a_reg, a_file):
                    files = files + [a_file]
                    break

    #
    # Remove make_doc.py from files list
    #


#     this_file_name = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Admin' + os.sep + 'make_doc.py')
#     this_file_ind = files.index(this_file_name)
#     files = files[:this_file_ind - 1] + files[this_file_ind + 1:]

# Not needed anymore
# modules = map(pythondoc.pythondoc.path2module, files)

#
# Set format to HTML4
#
#  formats = []
#  pythondoc.pythondoc.add_formatter('HTML4', formats)

#
# Set documentation directory to $VCODE_HOME/Doc/Modules
#
    doc_dir = posixpath.expandvars(vc_globals.doc_modules)

    #  pythondoc.pythondoc._options.add_value('main_directory', doc_dir)
    #  pythondoc.pythondoc._options.add_value('main_index', 1)

    # for a_module in modules:
    #     sys.stdout.write("   %s\n" % a_module)
    #     pythondoc.pythondoc.generate_pages(modules, formats)

    #
    # Generate the HTML doc for each module
    #
    cmd_line = 'e:\python\python.exe ' + pydoc_path + ' -i -f HTML4 -d ' + doc_dir + ' '
    for a_file in files:

        #
        # Check to see if HTML doc needs to be refreshed
        #
        a_match = re.match('.*?([^\\' + os.sep + ']*)\.py$', a_file)
        module_name = a_match.groups()[0]
        html_file = doc_dir + os.sep + module_name + '.html'

        if (util.last_mod(html_file) < util.last_mod(a_file)):
            print "   Updating documentation for module '%s'...\n" % module_name
            cmd = cmd_line + a_file
            os.system(cmd)
            if slow:
                print "   That was module '%s'...\n\n" % module_name
                raw_input("press enter to continue")

    #
    # Fix problem with references
    #
    fix_references(doc_dir)
Example #12
0
class Object:
    """A generic base class for all objects.

    **INSTANCE ATTRIBUTE**

    *none* --

    **CLASS ATTRIBUTE**

    *none* --

    This class implements useful behaviors for generic
    objects, such as:

    - safe attribute setting
    
    - pretty printing (not implemented yet)
    
    - "standard" constructor that:
    
       - automatically invoke constructors of all ancestor classes
       - automatically "declares" valid attributes (for use with safe __setattr__)
       - allows a subclass' constructor to inherit arguments (with default
         values if any) from the constructors of its ancestor clases

    Below is a more detailed description of the various features of the class.

    **SAFE ATTRIBUTE SETTING**

    When getting the value of an attribute, Python will issue an
    *AttributeError* if that attribute doesn't exist. However, it
    doesn't do that when trying to set the value of an inexistant
    attribute.

    The [Object] class defines a safe *__setattr__* method, which
    raises an exception when trying to set the value of an undeclared
    attribute (see below for instructions on how to declare an
    attribute).

    For performance reasons, these safe attribute setting methods are
    only invoked if environment variable *$PY_DEBUG_OBJECT=1*.

    Note that [Object] does not define a safe *__getattr__*
    method because Python already raises an exception when trying to
    get the value of an inexistant attribute.

    Profile tests on NT indicate that:

    - the speed of constructors for Object and non-Object instances
      are the same
    
    - the speed of attribute *gets* is the same for Object and
      non-Object instances
    
    - when *$PY_DEBUG_OBJECT=0*, the performance of attribute *sets*
      is the same for Object and non-Object instances
    
    - when *$PY_DEBUG_OBJECT=1*, attribute *sets* are slower by a
      factor of about 15 for Object instances than for non-Object
      instances


    **"DECLARING" VALID ATTRIBUTES**

    In order to use the safe *__setattr__* method, we need a way to tell it
    what the valid attributes are.

    You can do this simply by setting the attribute directly through
    *__dict__*. You can also use the [decl_attrs] method to declare a
    series of valid attributes with less typing.

    Typically, valid attributes should be set in this way, only in the
    *__init__* method. The rest of the time, they should be set in the
    normal way (or through [init_attrs]), so that the safe __setattr_
    method can intercept access to undeclared attributes..

    Example:
    
       #
       # declare like this inside __init__
       #
       self.__dict__['attr_name'] = None
       self.__dict__['an_other_attr_name'] = None
       
       #
       # or like this if you don't like brainless repetitive typing
       # 
       self.decl_attrs({'attr_name': None, 'an_other_attr_name': None})

       # 
       # set like this the rest of the time
       # 
       self.attr_name = None
       self.an_other_attr_name = None

       # 
       # or like this
       # 
       self.init_attrs({'attr_name': None, 'an_other_attr_name': None})


    Note that you don't need to declare attributes which you pass to [deep_construct]
    through its *attrs_this_class* argument, because [deep_construct]
    will declare them automatically for you.
    

    **STANDARD CONSTRUCTORS**

    The method [deep_construct] can be used to define standard
    constructors with the following properties:
    
    - automatically invokes constructors of all ancestor classes
    
    - automatically "declares" valid attributes (for use with safe *__setattr__*)
    
    - allows a subclass' constructor to inherit arguments (with
      default values if any) from the constructors of its ancestor
      classes

    This has many advantages.
    
    Example:
    
       class Person(Object):
          def __init__(self, name=None, age=None, **args_super):
              etc...
       class Employee(Person):
           def __init__(self, salary=None, **args_super):
               etc...
               
       some_employee = Employee(name='Alain', salary='not enough')

    Note how I was able to feed the *name* to *Employee.__init__*,
    eventhough it doesn't explicitly define that argument. That's
    because *Employee.__init__* "inherited" that argument from
    *Person.__init__*.

    Note also that I didn't have to specify the *age*
    argument. Although it's not obvious from the example, the standard
    constructor automatically sets it to the default *None*
    inherited from *Person.__init__*.

    Below are a series of examples showing how to use [deep_construct]
    to build different standard constructors.

    Note that the file *Admin/python.el* defines some Emacs-Lisp
    macros for writing template code for standard constructors.


    **EXAMPLE 1: Simple case**

    Let's start with a simple case.

    Suppose I want to create a standard class *Person* with attributes
    *name*, *citizenship*, and a standard subclass *Employee* with
    additional attribute *salary*. This would be done as follows.


    Example:
    
       class Person(Object):
          def __init__(self, name, citizenship=None, **args_super):
             self.deep_construct(Person, {'name': name, 'citizenship': citizenship}, args_super)

       class Employee(Person):
           def __init__(self, salary=None, **args_super):
             self.deep_construct(Employee, {'salary': salary}, args_super)

       #
       # This is OK
       #
       some_employee = Employee(name='Alain', salary='not enough')

       #
       # This raises an exception because we don't give a value for
       # compulsory argument name, which is inherited from Person.__init__
       #
       some_other_employee = Employee(salary='not enough')

    Simple no?

    Note how I was able to set attribute *name* through
    *Employee.__init__*, eventhough it is not an argument of that
    constructor.

    Note also that I didn't have to specify a value for
    *citizenship*, because that's only an optional argument inherited from 
    *Person.__init__*.

    Finally, note how construction of *some_other_employee* fails
    because I didn't specify a value for *name*, which is a compulsory
    argument inherited from *Person.__init__*.


    **EXAMPLE 2: Caution regarding compulsory constructor arguments**

    Because compulsory constructor arguments are inherited by
    subclasses, one should be careful not to create too many of
    them. Otherwise, the constructor of subclasses deep in the inheritance
    hierarchy can end up with a great number of compulsory
    arguments. For example, suppose we have a chain of 10 subclasses,
    each adding 3 new compulsory constructor arguments. The
    constructor of the 10th subclass in the chain would end up with 30
    compulsory arguments! The situation becomes even worse in the case
    of multiple inheritance.

    In general, it is better to define constructor arguments to be
    optional, except in cases where the argument has no sensible
    default value. Even in such cases, it's usually pretty safe to use
    *None* as the default value. Remember, this is Python, not C or C++. The
    worst that can happen is that the programer may at some point
    access the argument as though it was not a *None* value, in
    which case he/she will get a nice error message which will allow
    him/her to quickly identify the source of the problem.

    For example, consider the code below.

    Example:

       class Person(Object):
          def __init__(self, age=None):
             self.deep_construct(Person, {'age': age}, args_super)

       #
       # This results in the following error message:
       #
       # Traceback (innermost last):
       #    File "test.py", line 7, in ?
       #      a_person.age = a_person.age + 1
       #  TypeError: bad operand type(s) for +
       #
       a_person = Person()
       a_person.age = a_person.age + 1


        
    To identify the source of the problem, all the user has to do then
    is to print the content of *a_person.age* (using a trace or
    debugger) to figure out that it was left at its default of *None*.

    **EXAMPLE 3: Changing default of an ancestor constructor argument**

    Sometimes, you may want a subclass' constructor to use a default
    value for a constructor argument, which is different from the default
    value defined for the same argument in the constructor of some
    ancestor class.
    
    For example, suppose I know that 99% of the instances of *Person*
    I create will have canadian citizenship. I would like to create a
    standard subclass *MyPerson* whose default value for *citizenship*
    is *'Canadian eh?'*.

    You can do this simply by including *citizenship* and its new
    default value in the argument *new_default* of
    [Object.deep_construct].

    Note that you should use the *new_default* argument only to
    specify default values of arguments defined in some ancestor's
    constructor. To specify the default of an argument defined in the
    current class' constructor, assign a default value in the list of
    arguments to the current class' constructor.
    
    Example:
        
       class Person(Object):
          def __init__(self, name=None, citizenship=None, **args_super):
             self.deep_construct(Person, {'name': name, 'citizenship': citizenship}, args_super)

       class MyPerson(Person):
           #
           # Note that MyPerson.__init__ defines a new argument age. Its
           # default value is defined in MyPerson.__init__'s list of formal
           # arguments, NOT in new_default
           #
           def __init__(self, age=None, **args_super):
             #
             # Because citizenship is an argument of the ancestor Person,
             # we redefine its default using new_default argument.
             #
             self.deep_construct(MyPerson, {'age': age}, args_super, new_default={'citizenship': 'Canadian eh?'})

       #
       # This person is Canadian by default
       #
       some_person = MyPerson(name='Alain')

       #
       # But I can still override that in the call to MyPerson.__init__
       #
       some_other_person = MyPerson(name='Alain', citizenship='US citizen')


    
    **EXAMPLE 4: Enforcing value of an ancestor constructor argument**

    Sometimes, you may want to force the value of an argument defined
    in an ancestor's constructor. This is different from changing the
    default value (as in above example), because here, the user simply
    cannot call the constructor with a value different from the
    enforced value.
 
    In the above example, any instance of *MyPerson* will be Canadian,
    but only by defaul. I can still override that value to create, say
    a US citizens. Now suppose I want to create a class *Canadian*
    where it wasn't possible to override the default value of
    *citizenship='Canadian eh?'*.

    All I have to do is to list *citizenship* and its enforced value
    of *'Canadian eh?'* in the *enforce_value* argument to
    [deep_construct]. If *$PY_DEBUG_OBJECT=1*, this will raise a
    EnforcedConstrArg exception if the programmer calls the
    constructor with a value that's different from the enforced value.

    Note that if the enforced argument happens to be an attribute,
    enforcing its value in the constructor does not prevent the user
    from changing the attribute's value after construction. This is 
    exemplified by the last two lines in the code below.

    
    Example:
        
       class Person(Object):
          def __init__(self, name=None, citizenship=None, **args_super):
             self.deep_construct(Person, {'name': name, 'citizenship': citizenship}, args_super)

       class Canadian(Person):
          def __init__(self, **args_super):
             self.deep_construct(Canadian, {}, args_super, enforce_value={'citizenship': 'Canadian eh?'})

       #
       # This works
       #
       some_canadian = Canadian(name='Alain')

       #
       # This raises an exception because I try to override the enforced
       # value for citizenship.
       #
       pseudo_canadian = Canadian(name='Alain', citizenship='US citizen')

       #
       # But unfortunately, this still manages to create an instance of
       # Canadian with citizenship='US citizen'
       #
       pseudo_canadian = Canadian(name='Alain')
       pseudo_canadian.citizenship = 'US citizen'
        

    **EXAMPLE 5: Arguments which are not attributes**       

    Some of the constructor arguments may not correspond to attributes
    of the class. For example, suppose I want to be able to provide a
    file from which to read initial specification of a *Person* object. I
    don't want this file to be stored as an attribute of the object
    because then the file handle could not be released until the
    object is garbage collected.

    In such cases, all you have to do is to *NOT* pass the argument to 
    [deep_construct]'s *attrs_this_class* argument. 

    Example:
        
       class Person(Object):
          def __init__(self, name=None, citizenship=None, init_file=None, **args_super):
            #
            # Note: deep_construct will not create a init_file attribute
            #       because it's not in its attrs_this_class argument.
            #
            self.deep_construct(Person, {'name': name, 'citizenship': citizenship}, args_super)
            if init_file: self.init_from_file(init_file)

       # Person doesn't get a init_file attribute
       a_person = Person(init_file=open('C:/temp.txt', 'r'))
       try:
           x = a_person.init_file
       except:
           print 'See, a_person has no attribute called *init_file*'


    **EXAMPLE 6: Private attributes**

    Some attributes are private, that is they are not supposed to be
    manipulated directly by the user.

    In the above example, suppose I want to be able to determine if the
    initialisation file has changed since the last time I initialised
    the instance of *Person*. I would do that by adding an attribute
    *date_last_read* which stores the date at which the instance was
    last initialised from file. Obviously, I don't want the programmer
    to set this value through constructor arguments.

    In this case, all I have to do is to exclude *date_last_read* from
    *Person.__init__*'s list of arguments, and declare it directly in
    *__init__* using [decl_attrs].

    Example:
        
       class Person(Object):
          #
          # Note how date_last_read is absent from list of arguments
          #
          def __init__(self, name=None, citizenship=None, init_file=None, **args_super):
             #
             # Instead, date_last_read attribute is declared directly here.
             #
             self.decl_attrs({'date_last_read': localtime()})
             #
             # No need to pass date_last_read to deep_construct, because it
             # was already declared above.
             # 
             self.deep_construct(Person, {'name': name, 'citizenship': citizenship}, args_super)
             if init_file: self.init_from_file(init_file)
       #
       # This works, and date_last_read ends up being set at current time.
       # 
       a_person = Person(init_file=FileObject(path='C:/person.dat'))
       #
       # This raises an exception because date_last_read is not a constructor
       # argument
       #
       a_person = Person(init_file=FileObject(path='C:/person.dat'), date_last_read=231233)

    **EXAMPLE 7: Doing other initialisation besides attribute setting**

    Often, a constructor needs to do more than just set attribute
    values. To do this, simply add code after the call to [deep_construct].

    In the previous example, we added code for conditionally calling
    *self.init_from_file(init_file)* after [deep_construct].


    **EXAMPLE 8: Subclassing from non-standard classes**

    Sometimes you will want to create a standard class which is a
    subclass of a non-standard class, that is, a class that doesn't
    have a standard constructor.

    In such cases, you would simply add the non-standard class
    to the *exclude_bases* argument of [deep_construct], and invoke
    the non-standard constructor manually in *__init__*.

    For example, suppose I want *Person* to also be a subclass of
    *AnimatedCharacter*, but *AnimatedCharacter.__init__* is not a
    standard constructor. 


    Example:
    
       class AnimatedCharacter():
          def __init__(self, animation_file, frames_per_sec=40):
              etc...
              
       class Person(Object):
          def __init__(self, name=None, citizenship=None, **args_super):
              etc...

       class AnimatedPerson(Person, AnimatedCharacter)
          def __init__(self, , animation_file, frames_per_sec=40, **args_super):
             self.deep_construct(AnimatedPerson, {'animation_file': animation_file, 'frames_per_sec': frames_per_sec}, args_super, exclude_bases={AnimatedCharacter: 1})
             AnimatedCharacter.__init__(self, animation_file, frames_per_sec=frames_per_sec)

       an_animated_person = AnimatedPerson(name='Alain', animation_file='C:/People/Alain.dat')


    Note that the only reason we have to exclude *AnimatedCharacter*
    from the list of automatically built superclasses, is that
    *AnimatedCharacter.__init__* doesn't have a catch-all argument
    *\*\*args_super*. If *AnimatedCharacter.__init__* DID have such a
    catch-all argument, we wouldn't have to exclude it, even if it
    didn't make use of the other aspects of the standard constructor.

    Note also that I still get all of the benefits from the standard
    constructor of *Person*, i.e. I can inherit the arguments of
    *Person.__init__* without additional work.

    However, if I want to inherit the arguments of
    *AnimatedCharacter.__init__*, I have to repeat them in the list of
    arguments for *AnimatedPerson.__init__* and then pass them to
    *AnimatedCharacter.__init__* manually.

    Note also that in *exclude_bases*, I specify the class object
    itself, not the name of the classe, that is:

    *exclude_bases = {AnimatedPerson: 1}*

    as opposed to

    *exclude_bases = {'AnimatedPerson': 1}*
        
    .. [decl_attrs] file:///./Object.Object.html#Object.Object.decl_attrs
    .. [init_attrs] file:///./Object.Object.html#Object.Object.init_attrs
    .. [deep_construct] file:///./Object.Object.html#Object.Object.deep_construct"""

    #
    # Safe __setattr__ method is defined in file 'safe_setattr.py'.
    # Load it only if environment variable PY_DEBUG_OBJECT=1
    #
    if (os.environ.has_key('PY_DEBUG_OBJECT')
            and (os.environ['PY_DEBUG_OBJECT'] != '0')):
        code_file = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Mediator' +
                                         os.sep + 'safe_setattr.py')
        execfile(code_file)

    def __init__(self, **args_super):
        pass

    def deep_construct(self,
                       this_class,
                       attrs_this_class,
                       args_super,
                       new_default={},
                       enforce_value={},
                       exclude_bases={}):
        """Build an instance of a class.

        Basically, this method:
        - declares and initialise all attributes listed in *attrs_this_class*
        - invokes the *__init__* of all superclasses (with the exclusion of those listed in *exclude_bases*), passing them arguments in *args_super*

        *CLASS* this_class -- Class that we want to build. This is a
         class object as opposed to the name of a class. Constructors
         of immediate superclasses of *this_class* are called
         automatically, except if they are listed in *{CLASS: 1}
         exclude_bases*.

        *{STR: ANY}* attrs_this_class -- New attributes (and their
         values) defined by class *this_class*. The keys are the names
         of the attributes and the values are the values of the
         attributes (either default values or values passed to
         *this_class.__init__*). An attribute with the appropriate
         name will be declared automatically and initialsed to the
         value specified in *attrs_this_class*.
        
        *{STR: ANY}* args_super -- Arguments received by
        *this_class.__init__* but not recognised by it. These are
        assumed to be arguments defined in the *__init__* of some
        ancestor class and are just passed up the construction
        chain. Keys of *args_super* correspond to the names of the
        arguments and the values corresponds to the values received
        for them by *this_class.__init__*

        *{STR: ANY}* new_default={} -- Used to change the default
         value of an ancestor constructor argument. In other words, if
         *this_class.__init__* was called without specifying a value
         for an argument that's listed in *new_default*, the default
         value defined in *new_default* will be used instead of
         whatever default might be defined in the constructor
         of an ancestor class. However, if the constructor was called
         WITH a specific value for that argument, that specific value
         will be used instead of both the defaults defined in
         *new_default* and the constructor of ancestor classes. Keys
         of *new_default* correspond to argument names, and values
         correspond to the new default values. If you don't specify a
         value of *new_default*, it defaults to *{}*, which means that
         the defaults of none of the ancestor constructor arguments
         are redefined by *this_class*.
        
        *{STR: ANY}* enforce_value={} -- Lists of arguments with
         enforced values. If the constructor is called with a value
         for an argument that is different from the value specified
         for it in *enforce_value*, then an [EnforcedConstrArg]
         exception will be raised. Also, if the constructor is called
         without specifying a value for a particular argument, then
         the value defined in *enforce_value* (if it exists) will be
         used instead of whatever default might be defined in an
         ancestor class. Keys of *enforce_value* correspond to
         argument names and values correspond to the enforced
         values. If you don't specify a value for *enforce_value*, it
         defaults to *{}*, which means that *this_class.__init__* does
         not enforce the value of any argument.
          
                 
       *{CLASS: BOOL}* exclude_bases -- Immediate base classes whose
        constructors should not be called automatically. If an
        immediate superclass of *this_class* is listed in
        *exclude_bases*, then we don't automatically call its
        constructor. It is assumed that the programmer will call the
        constructor manually in *this_class.__init__*. If you do not
        specify a value for *exclude_bases*, it will default to *{}*,
        which means that the constructor of all immediate super
        classes will be called automatically.


        .. [EnforcedConstrArg] file:///./Object.EnforcedConstrArg.html
        .. [Object] file:///./Object.Object.html"""

        #        debug.trace('Object.deep_construct', 'this_class=%s' % this_class)

        #
        # Redefine the default value of some ancestor constructor
        # arguments.
        #
        for an_arg in new_default.items():
            if not args_super.has_key(an_arg[0]):
                #
                # this_class.__init__  called without a value for the argument.
                # Use the default value provided by this_class.__init__,  instead
                # of waiting for ancestor class to set it to its own default
                # value.
                #
                args_super[an_arg[0]] = an_arg[1]

        #
        # Enforce values of some superclass arguments
        #
        for an_arg in enforce_value.items():
            if args_super.has_key(an_arg[0]):
                #
                # this_class.__init__ called with a value for this argument
                #
                if args_super[an_arg[0]] != an_arg[1]:
                    #
                    # The value provided is not the same as the enforced one.
                    # Raise an exception
                    #
                    raise EnforcedConstrArg(
                        'The value of argument %s in %s.__init__ is enforced at \'%s\', and cannot be changed.'
                        % (an_arg[0], repr(this_class), an_arg[1]))
            else:
                #
                # this_class.__init__ called without a value for this argument.
                # Set it to the enforced value
                #
                args_super[an_arg[0]] = an_arg[1]

        #
        # Declare and initialise new attributes which are defined by
        # this_class.
        #
        # Note: We do this BEFORE invoking constructor of superclasses
        #       because the constructors of superclasses might invoke
        #       some virtual method whose overriden implementation
        #       assumes that the attributes are defined.
        #
        #       For example, this happens often when the superclass
        #       constructor invokes a factory method to build one of
        #       its members. The concrete implementation of that
        #       factory method often needs to access attributes
        #       of the subclass.
        #
        self.decl_attrs(attrs_this_class)

        #
        # Invoke constructor of the superclasses, feeding them arguments
        # not recognised by this_class.__init__
        #
        for a_base in this_class.__bases__:
            if not exclude_bases.has_key(a_base):
                try:
                    apply(a_base.__init__, [self], args_super)
                except TypeError:
                    msg = "TypeError while initializing base %s of class %s\n" \
                        % (str(a_base), str(this_class))
                    sys.stderr.write(msg)
                    msg = "keyword arguments were: %s\n" % str(args_super)
                    sys.stderr.write(msg)
                    raise

    def decl_attrs(self, attrs):
        """Define new attributes for *self*

        Attributes are directly through self.__dict__, thus bypassing safe
        __setattr__.

        **INPUTS**

        *{STR: ANY}* attrs -- dictionary with attribute name as the keys and
         initial values as the values.

        **OUTPUTS**

        *none* -- 
        """
        for an_attr_def in attrs.items():
            self.__dict__[an_attr_def[0]] = an_attr_def[1]

    def init_attrs(self, attrs):
        """Initialises existing attributes

        Attributes are only set if they already exist in
         *self.__dict__*. Otherwise, an *AttributeError* exception is
         raised (provided PY_DEBUG_OBJECT=1).
        
        **INPUTS**

        *{STR: ANY}* attrs -- dictionary with attribute name as the keys and
         default values as the values.

        **OUTPUTS**

        *none* -- 
        """
        for key, value in attrs.items():
            setattr(self, key, value)

    def possibly_init_attrs(self, attrs):
        """Initialises existing attributes, unless those attributes
        already exist
        
        **INPUTS**

        *{STR: ANY}* attrs -- dictionary with attribute name as the keys and
         default values as the values.

        **OUTPUTS**

        *none* -- 
        """
        for key, value in attrs.items():
            if not self.__dict__.has_key(key):
                setattr(self, key, value)
Example #13
0
class Object:
    """A base class for all VoiceCode objects

    This class implements various useful behaviors for generic
    objects, such as:

    - safe attribute setting
    - deep constructor
    - pretty printing???
    

    **SAFE ATTRIBUTE SETTING***

    When getting the value of an attribute, Python will issue an
    *AttributeError* if that attribute doesn't exist. However, it
    doesn't do that when trying to set the value of an inexistant
    attribute.

    The [Object] class defines a safe *__setattr__* method, which raise an
    exception when trying to set the value of an inexistant attribute.

    For performance reasons, these safe attribute setting methods are
    only invoked if environment variable *$PY_DEBUG_OBJECT=1*.

    Note that this class does not define a safe *__getattr__*
    method because Python already raises an exception when trying to
    get the value of an inexistant attribute.

    Profile tests on NT indicate that:

    - the speed of constructors for Object and non-Object instances are the same
    - the speed of attribute *gets* is the same for Object and non-Object instances
    - when *$PY_DEBUG_OBJECT=0*, the performance of attribute *sets* is the same for Object and non-Object instances
    - when *$PY_DEBUG_OBJECT=1*, attribute *sets* are slower by a factor of about 15 for Object instances than for non-Object instances


    **DEEP CONSTRUCTORS**

    By default, when constructing an instance of a class, Python does
    not call the constructor of all the ancestor classes. This means
    that the constructor of each class must set the values of the
    attributes defined by all of its ancestors, otherwise reading the
    value of an ancestor attribute (or setting it when
    *PY_DEBUG_OBJECT=1*) results in an *AttributeError*. This also
    means that subclasses cannot inherit default values of ancestor
    attributes from their ancestor classes.
    
    The [Object] class defines a method [deep_construct], which can be
    used to create "standard" constructors with interesting properties:

    - it automatically invoke the constructor of any superclass that has a "standard" constructor
    - it inherits default attribute values from ancestor classes
    - you can call it without arguments to obtain a consistent default instance
    - you can override the default value of any attribute (including ones defined by ancestor classe) simply by passing a named argument to the constructor
    - you can leave the value of any attribute (including ones defined by ancestor classe) at its default value, simply by not passing a named argument for that attribute

    Below is a template for such a standard constructor.

    Example:

       class AClass(StdClass1, ..., StdClassN, NonStdClass1, ..., NonStdClassK):
          def __init__(self, attr1=val1, ..., attrN=valN, **attrs):
              
             self.deep_construct(AClass, {'attr1': val1, ..., 'attrN': valN}, attrs, exclude_bases={NonStdClass1: 1, ..., NonStdClassK: 1})
             
             <Code for explicitely calling NonStdClass1.__init__, ..., NonStdClassK.__init__ with appropriate arguments>
             
             <Any other initialisation that can't be done automatically
              through *self.deep_construct*>

    Here, *StdClass1, ..., StdClassN* are "standard" classes, that is
    classes that have standard constructor. The constructor of those
    classes can be invoked automatically because it doesn't have
    any compulsory arguments.

    *NonStdClass1, ..., NonStdClassK* are "non-standard" classes,
     i.e. classes whose constructor has some compulsory arguments. The
     constructor of those non-standard classes can therefore not be
     called automatically (which is why they are set in the
     *exclude_bases* argument and their constructor is explicitely
     called after the call to *self.deep_construct*)
    
    Attributes *attr1, ..., attrN* are the new attributes defined by
    *AClass*, and *val1, ..., valN* are their default values.

    The argument *{STR: ANY} **attrs* collects any named arguments fed
    to the constructor which don't correspond to an attribute defined
    by this class. These will be used to set the values of attributes
    defined in ancestor classes.
                       
    Note that the file *Admin/python.el* contains an Emacs macro
    *py-obclass* which automatically types this kind of template code
    for a class and its constructor

    **INSTANCE ATTRIBUTE**

    *none* --

    **CLASS ATTRIBUTE**

    *none* --

    .. [def_attrs] file:///./Object.Object.html#Object.Object.def_attrs
    .. [init_attrs] file:///Object.Object.html#Object.Object.init_attrs"""

    #
    # Safe __setattr__ method is defined in file 'safe_setattr.py'.
    # Load it only if environment variable PY_DEBUG_OBJECT=1
    #
    if (os.environ.has_key('PY_DEBUG_OBJECT')
            and (os.environ['PY_DEBUG_OBJECT'] != '0')):
        code_file = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Mediator' +
                                         os.sep + 'safe_setattr.py')
        execfile(code_file)

    def __init__(self):
        pass

    def deep_construct(self,
                       this_class,
                       attrs_this_class,
                       attrs_superclasses,
                       exclude_bases={}):
        """Build an instance of a class.

        Make *[Object] self* into an instance of class *CLASS this_class*.

        Automatically call constructors of superclasses of
        *this_class* (except for classes listed in *{CLASS: 1}
        exclude_bases*). Constructors are called with no arguments.
        
        Set attributes to the values listed in *{STR: ANY}
        attrs_this_class* and *{STR: ANY} attrs_cupserclasses*. These
        attributes are set even if they do not exist in
        *self.__dict__*.
        
        listed in *exclude_bases* argument). These constructors are
        called with no arguments.

        .. [Object] file:///./Object.Object.html"""

        for a_base in this_class.__bases__:
            if not exclude_bases.has_key(a_base):
                a_base.__init__(self)

        for an_attr_def in attrs_this_class.items():
            self.__dict__[an_attr_def[0]] = an_attr_def[1]

        for an_attr_def in attrs_superclasses.items():
            self.__dict__[an_attr_def[0]] = an_attr_def[1]


#      def def_attrs(self, attrs):
#          """Define new attributes for *self*

#          Attributes are set even if they do not exist in
#          *self.__dict__*.

#          **INPUTS**

#          *{STR: ANY}* attrs -- dictionary with attribute name as the keys and
#           default values as the values.

#          **OUTPUTS**

#          *none* --
#          """
#          for an_attr_def in attrs.items():
#              self.__dict__[an_attr_def[0]] = an_attr_def[1]

    def init_attrs(self, attrs):
        """Initialises existing attributes

        Attributes are only set if they already exist in
         *self.__dict__*. Otherwise, an *AttributeError* exception is
         raised (provided PY_DEBUG_OBJECT=1).
        
        **INPUTS**

        *{STR: ANY}* attrs -- dictionary with attribute name as the keys and
         default values as the values.

        **OUTPUTS**

        *none* -- 
        """
        for an_attr_init in attrs.items():
            setattr(self, an_attr_init[0], an_attr_init[1])
Example #14
0
def runme():

    #
    # Path of the pythondoc or pydoc.py script
    #
    pydoc_path = find_pydoc_path()
    if not pydoc_path:
        sys.stderr.write("unable to locate pydoc script\n")
        quit()
    sys.stderr.write("pydoc was found in\n" + pydoc_path + "\n")
       
    #
    # Get names of py files to document
    #
    #    glob_pattern = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Mediator' + os.sep + '*.py')
    glob_pattern = posixpath.expandvars('$VCODE_HOME' + os.sep + '*' + os.sep + '*.py')
    files = glob.glob(glob_pattern)

    #
    # Remove files that don't match name patter
    #
    slow = 0
    if sys.argv: 
        opts, args = util.gopt(['s', None])
    # parse command line options and arguments
        if opts:
            if opts['s']:
                slow = 1
        regs_file_name = args
    if regs_file_name:
        orig_files = files
        files = []
        for a_file in orig_files:
            for a_reg in regs_file_name:
                a_reg = '[\s\S]*\\' + os.sep + a_reg + '$'
                if re.match(a_reg, a_file):
                    files = files + [a_file]
                    break

    #
    # Remove make_doc.py from files list
    #
#     this_file_name = posixpath.expandvars('$VCODE_HOME' + os.sep + 'Admin' + os.sep + 'make_doc.py')
#     this_file_ind = files.index(this_file_name)
#     files = files[:this_file_ind - 1] + files[this_file_ind + 1:]
   
      
    # Not needed anymore
    # modules = map(pythondoc.pythondoc.path2module, files)
    
    #
    # Set format to HTML4
    #
    #  formats = []
    #  pythondoc.pythondoc.add_formatter('HTML4', formats)
    
    #
    # Set documentation directory to $VCODE_HOME/Doc/Modules
    #
    doc_dir = posixpath.expandvars(vc_globals.doc_modules)
   
    #  pythondoc.pythondoc._options.add_value('main_directory', doc_dir)
    #  pythondoc.pythondoc._options.add_value('main_index', 1)
   
    # for a_module in modules:
    #     sys.stdout.write("   %s\n" % a_module)
    #     pythondoc.pythondoc.generate_pages(modules, formats)
       
    #
    # Generate the HTML doc for each module
    #
    cmd_line = 'e:\python\python.exe ' + pydoc_path + ' -i -f HTML4 -d ' + doc_dir + ' '
    for a_file in files:
           
        #
        # Check to see if HTML doc needs to be refreshed
        #
        a_match = re.match('.*?([^\\' + os.sep + ']*)\.py$', a_file)
        module_name = a_match.groups()[0]
        html_file = doc_dir + os.sep + module_name + '.html'

        if (util.last_mod(html_file) < util.last_mod(a_file)):
            print "   Updating documentation for module '%s'...\n" % module_name
            cmd = cmd_line + a_file
            os.system(cmd)
            if slow:
                print "   That was module '%s'...\n\n" % module_name
                raw_input("press enter to continue")

    #
    # Fix problem with references
    #
    fix_references(doc_dir)
Example #15
0
 def update_event(self, inp=-1):
     self.set_output_val(0, posixpath.expandvars(self.input(0)))