GlobalID.py :  » Database » Modeling-Framework » Modeling-0.9 » Modeling » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Database » Modeling Framework 
Modeling Framework » Modeling 0.9 » Modeling » GlobalID.py
# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------


"""
GlobalID

  A GlobalID is used to Uniquely identify an object within the framework ;
  more precisely, speaking of an EditingContext 'ec', any object 'o'
  registered within 'ec' corresponds to one and only one GlobalID --see
  EditingContext.globalIDForObject() and EditingContext.objectForGlobalID().

  Hence, it is completely equivalent to speak in terms of objects or in terms
  of GlobalIDs when talking relatively to a given EditingContext.

  There are two type of GlobalIDs:

    - TemporaryGlobalID are assigned to newly created objects (see
      EditingContext.insertObject()), which are not yet saved within a
      database
      
    - KeyGlobalID identifies an object that does exist in a database store (it
      can be either a fully-initialized/already fetched object, or a ``fault''
      object (a ``ghost'' in ZODB.Persistence jargon) that still needs to be
      fetched.
      
  Both types are immutable types.
    
  CVS information

    $Id: GlobalID.py 932 2004-07-20 06:21:57Z sbigaret $
  
"""

__version__='$Revision: 932 $'[11:-2]

from interfaces.GlobalID import IKeyGlobalID,ITemporaryGlobalID

import time, socket

GlobalIDChangedNotification='GlobalIdChangedNotification'

def globalIDWithEntityName(entityName, informations=None):
  """
  Returns a new GlobalID based on the supplied informations.

  Parameter 'informations' can be either:

    - None, in which case a TemporaryGlobalId is returned, or

    - an object implementing XXX,

    - a dictionary '{PK_name: value}', containing all entities' PKs

  In the two latter cases a KeyGlobalID is returned.

  """
  if informations is None:
    return TemporaryGlobalID()
  else:
    return KeyGlobalID(entityName, informations)
  
## GlobalID
class KeyGlobalID:
  """
  KeyGlobalID

  Important note: the internal state of KeyGlobalID objects is considered
    read-only, and at no time the framework expects their internal values to
    change. Trying to change them will certainly trigger wrong and possibly
    bad behaviour, including (not exhaustively): loss of data, apparition of
    dangling references, confusion in the objects' changes that are made
    persistent, etc.
  
  """
  __implements__=(IKeyGlobalID, )
  
  __is_temporary__=0

  def __init__(self, entityName, keyValues):
    """
    Initializes a new GlobalID with the following parameters:

    Parameters:
    
      entityName -- the name of the corresponding object's entityName
        (remember a GlobalID acts as a label that sticks to a particular
        object),
      
      keyValues -- a dictionary ; the entity's primary key(s)'s names are its
        keys, map to their respective values.

    """
    self.__dict__['_entityName']=entityName
    self.__dict__['_keyValues']=keyValues
    #self.__hash=hash('%s/%s'%(self._entityName, str(self._keyValues)))
    self._buildHashCode()
    
  def entityName(self):
    return self._entityName
    
  def isTemporary(self):
    """
    Returns 'false'.
    """
    return 0

  def keyCount(self):
    """
    Returns the number of entries supplied in 'keyValues' when the GlobalID
    was initialized. For example, if an object is stored in the database in a
    table which has a simple (as opposed to a compound-) primary key, its
    GlobalID will return '1' (one).
    """
    return len(self._keyValues)
  
  def keyValues(self):
    """
    Return the object's key values, as specified when the object was
    initialized.

    See also: __init__()
    """
    return self._keyValues.copy()
  
  def __eq__(self, aGlobalId):
    """
    Compares self with 'aGlobalID'

    A GlobalID is equal to another one iff:

      - they both are GlobalIDs (either KeyGlobalID or TemporaryGlobalID)

      - they both are KeyGlobalID, with the same entityName() and keyValues()

      - they both are TemporaryGlobalID, with the same internal state (as
        exposed by __str__)

    """
    if not hasattr(aGlobalId, '__is_temporary__'): return 0
    if aGlobalId.__is_temporary__: return 0
    if self._entityName!=aGlobalId._entityName or \
       self._keyValues !=aGlobalId._keyValues : return 0
    return 1
    
  def __cmp__(self, aGlobalId):
    """

    """
    hs=hash(self)
    hp=hash(aGlobalId)
    if hs<hp: return -1
    elif hs>hp: return 1
    else: return 0
    
  def __str__(self):
    """
    Returns a string representation of the GlobalID. This string representation
    is unique among GlobalIDs.
    """
    return '<KeyGlobalID: %s %s at %s>'%(self._entityName,
                                         str(self._keyValues),
                                         hex(id(self)))

  def __hash__(self):
    return self.__hash
  
  def _buildHashCode(self):
    "Computes the hash code for the object."
    # According to python doc., the two lists keys() and values() directly
    # corresponds if they are called with no intervening modification to
    # the dictionary. So we can safely add these two lists and derive the hash
    # code from that (which is obviously order-dependent)
    l=tuple(self._keyValues.keys()+self._keyValues.values())
    self.__dict__['_KeyGlobalID__hash']=hash(self._entityName)^hash(l)

  def __setattr__(self, name, value):
    "Raises TypeError since this is an immutable object"
    raise TypeError, 'object has read-only attributes'

## Index for TemporaryGlobalID
from threading import RLock
temporaryGlobalIDIndex=0
TemporaryGlobalIDIndex_lock=RLock()
lock=TemporaryGlobalIDIndex_lock.acquire
unlock=TemporaryGlobalIDIndex_lock.release
def nextTemporaryIndex():
  "This is part of the initialization process of TemporaryGlobalID"
  lock()
  try:
    global temporaryGlobalIDIndex
    temporaryGlobalIDIndex += 1
    return temporaryGlobalIDIndex
  finally:
    unlock()
    
## TemporaryGlobalID
class TemporaryGlobalID:
  """
  TemporaryGlobalID

  Important note: the internal state of KeyGlobalID objects is considered
    read-only, and at no time the framework expects their internal values to
    change. Trying to change them will certainly trigger wrong and possibly
    bad behaviour, including (not exhaustively): loss of data, apparition of
    dangling references, confusion in the objects' changes that are made
    persistent, etc.
  
  """
  __implements__=(ITemporaryGlobalID,)
  __is_temporary__=1

  # We now cache the fqdn (_host) and ipaddrlist: when an host has problems
  # resolving dns entries this can hang a few seconds, and
  # EditingContext.insert() then appears to be really slow (bug #804756)
  _host=socket.getfqdn()
  _ipaddrlist=socket.gethostbyname_ex(_host)[2]
  
  def __init__(self, *args, **kw):
    "Initializes a new TemporaryGlobalID. Arguments are currently ignored."
    self.__dict__['_index']=nextTemporaryIndex()
    self.__dict__['_ip']=self.nonLocalIPIfAvailable(self._ipaddrlist)
    self.__dict__['_time']=time.strftime("%Y%m%d%H%M%S")
    self.__dict__['_TemporaryGlobalID__hash']=hash("%s/%s/%s/%s"%(self._index,self._time, self._host,self._ip))

  def isTemporary(self):
    "Returns true"
    return 1
  
  def __eq__(self, aGlobalID):
    """
    Compares self with 'aGlobalID'

    A GlobalID is equal to another one iff:

      - they both are GlobalIDs (either KeyGlobalID or TemporaryGlobalID)

      - they both are KeyGlobalID, with the same entityName() and keyValues()

      - they both are TemporaryGlobalID, with the same internal state (as
        exposed by __str__)

    """
    if not hasattr(aGlobalID, '__is_temporary__'): return 0
    if not aGlobalID.__is_temporary__: return 0
    if self._host  != aGlobalID._host  or \
       self._index != aGlobalID._index or \
       self._ip    != aGlobalID._ip    or \
       self._time  != aGlobalID._time:
      return 0
    return 1

  def __str__(self):
    """
    Returns a string representation of the GlobalID. This string representation
    is unique among GlobalIDs.
    """
    return '<TemporaryGlobalID %s / %s / %s [%s] at %s>'%(self._index,self._time, self._host,self._ip, hex(id(self)))

  def __hash__(self):
    return self.__hash
  
  def nonLocalIPIfAvailable(self, ipaddrList):
    if not ipaddrList:
      return '127.0.0.1'
    for ip in ipaddrList:
      if ip!='127.0.0.1':
        return ip
    return '127.0.0.1'

  def __setattr__(self, name, value):
    "Raises TypeError since this is an immutable object"
    raise TypeError, 'object has read-only attributes'

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.