# -*- coding: utf-8 -*-
#--------------------------------
#$Date$
#$Author$
#$Revision$
#--------------------------------
#Copyright (C) 2007 Alexander Koshelev (daevaorn@gmail.com)
from django.utils.functional import curry
from django.utils.encoding import smart_unicode,smart_str
from django.utils.safestring import SafeString
SIMPLE_ATTRS = [ "fn",
"nickname",
"sort-string",
"url",
"tz",
"photo",
"logo",
"sound",
"bday",
"title",
"role",
"category",
"note",
"class",
"key",
"mailer",
"uid",
"rev" ]
COMPLEX_ATTRS = { "n" : ( "family-name", "given-name", "additional-name", "honorific-prefix", "honorific-suffix" ),
"email" : ( "type", "value" ),
"tel" : ( "type", "value" ),
"geo" : ( "latitude", "longitude" ),
"org" : ( "organization-name", "organization-unit" ),
"adr" : ( "post-office-box",
"extended-address",
"street-address",
"locality",
"region",
"postal-code",
"country-name",
"type",
"value")
}
ATTRS_TYPES = { "adr" : ( 'work', 'home', 'pref', 'postal', 'dom', 'intl' ),
}
def simple_format( value, name ):
return SafeString( smart_str( '%s' % ( name, value ) ) )
def _hcard_simple_field( self,instance,name,getter ):
value = getter( self, instance )
formatter = getattr( self, "format_%s" % name, curry( simple_format, name = name ) )
return SafeString( smart_str( formatter( value ) ) )
def _hcard_complex_render( name, values ):
res = '' % name
for key in COMPLEX_ATTRS[ name ]:
res += '%s' % ( key, values.get( key ) )
res += ''
return SafeString( res )
def format_complex( value, name ):
if isinstance( value, ( list, tuple ) ):
res = []
for v in value:
res.append( _hcard_complex_render( name, v ) )
return "".join( res )
elif isinstance( value, dict ):
return _hcard_complex_render( name, value )
else:
raise AttributeError, "hCard attribute with name %s must be dict or list/tuple of dicts" % name
def _hcard_complex_field( self, instance, name, getter ):
value = getter( self, instance )
formatter = getattr( self, "format_%s" % name, curry( format_complex, name = name ) )
return SafeString( smart_str( formatter( value ) ) )
make_name = lambda key: key #"hcard_%s" %
def value_getter( instance, name ):
attr = getattr( instance, name )
if callable( attr ):
return attr()
return attr
def value_getter_with_instance( obj, instance, name ):
attr = getattr( obj, name )
if callable( attr ):
return attr( instance = instance )
return attr
def resolve_value( format, instance, name ):
bits = name.split( '.' )
attr = instance
try:
for bit in bits:
attr = value_getter( attr, bit )
return attr
except AttributeError, e:
pass
attr = format
try:
for bit in bits:
attr = value_getter_with_instance( attr, instance, bit )
return attr
except AttributeError:
raise
def make_methods( hcard, keys, func ):
attrs = {}
for key in keys:
attr_name = make_name( key )
if key in hcard:
field_name = hcard.pop( key )
attrs[ attr_name ] = curry( func,
name = key,
getter = curry( resolve_value, name = field_name ) )
else:
attrs[ attr_name ] = lambda obj: ""
return attrs
class HcardMetaclass( type ):
def __new__( cls, name, bases, attrs ):
attrs.update( make_methods( attrs, SIMPLE_ATTRS, _hcard_simple_field ) )
attrs.update( make_methods( attrs, COMPLEX_ATTRS.keys(), _hcard_complex_field ) )
return type.__new__( cls, name, bases, attrs )
class FormatProxy( object ):
def __init__(self, format, instance ):
self.format = format
self.instance = instance
def __getattr__( self, name ):
return getattr( self.format, name )( self.instance )
class HcardFormat( object ):
__metaclass__ = HcardMetaclass
def __get__(self, instance, instance_type = None ):
return FormatProxy( self, instance )
def __set__(self, instance, value ):
pass
def format_email( self, value ):
return """
%(type)s
%(value)s
""" % value
def format_bday( self, value ):
title = value.strftime( "%Y-%m-%d" )
text = value.strftime( "%B %d, %Y" )
return """%s""" % ( title, text )