Back to index

plone3  3.1.7
Classes | Functions | Variables
CMFPlone.utils Namespace Reference

Classes

class  BrowserView
class  IndexIterator
class  RealIndexIterator
class  ToolInit

Functions

def parent
def context
def createBreadCrumbs
def createNavTree
def createSiteMap
def _getDefaultPageView
def isDefaultPage
def getDefaultPage
def isIDAutoGenerated
def lookupTranslationId
def pretty_title_or_id
def getSiteEncoding
def portal_utf8
def utf8_portal
def getEmptyTitle
def typesToList
def normalizeString
def _createObjectByType
def safeToInt
def versionTupleFromString
def getFSVersionTuple
def transaction_note
def base_hasattr
def safe_hasattr
def safe_callable
def safe_unicode
def tuplize
def _detuplize
def flatten
def directlyProvides
def classImplements
def classDoesNotImplement
def webdav_enabled
def _unrestricted_rename
def _getSecurity
def scale_image
def isLinked

Variables

tuple PACKAGE_HOME = Globals.package_home(globals())
tuple WWW_DIR = join(PACKAGE_HOME, 'www')
 PIL_SCALING_ALGO = Image.ANTIALIAS
int PIL_QUALITY = 88
tuple MEMBER_IMAGE_SCALE = (75, 100)
dictionary IMAGE_SCALE_PARAMS
list _marker = []
tuple release_levels = ('alpha', 'beta', 'candidate', 'final')
dictionary rl_abbr = {'a':'alpha', 'b':'beta', 'rc':'candidate'}

Function Documentation

def CMFPlone.utils._createObjectByType (   type_name,
  container,
  id,
  args,
  kw 
) [private]
Create an object without performing security checks

invokeFactory and fti.constructInstance perform some security checks
before creating the object. Use this function instead if you need to
skip these checks.

This method uses some code from
CMFCore.TypesTool.FactoryTypeInformation.constructInstance
to create the object without security checks.

Definition at line 364 of file utils.py.

00364 
00365 def _createObjectByType(type_name, container, id, *args, **kw):
00366     """Create an object without performing security checks
00367 
00368     invokeFactory and fti.constructInstance perform some security checks
00369     before creating the object. Use this function instead if you need to
00370     skip these checks.
00371 
00372     This method uses some code from
00373     CMFCore.TypesTool.FactoryTypeInformation.constructInstance
00374     to create the object without security checks.
00375     """
00376     id = str(id)
00377     typesTool = getToolByName(container, 'portal_types')
00378     fti = typesTool.getTypeInfo(type_name)
00379     if not fti:
00380         raise ValueError, 'Invalid type %s' % type_name
00381 
00382     # we have to do it all manually :(
00383     p = container.manage_addProduct[fti.product]
00384     m = getattr(p, fti.factory, None)
00385     if m is None:
00386         raise ValueError, ('Product factory for %s was invalid' %
00387                            fti.getId())
00388 
00389     # construct the object
00390     m(id, *args, **kw)
00391     ob = container._getOb( id )
00392 
00393     return fti._finishConstruction(ob)
00394 

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils._detuplize (   interfaces,
  append 
) [private]

Definition at line 527 of file utils.py.

00527 
00528 def _detuplize(interfaces, append):
00529     if isinstance(interfaces, (tuple, list)):
00530         for sub in interfaces:
00531             _detuplize(sub, append)
00532     else:
00533         append(interfaces)

Here is the caller graph for this function:

def CMFPlone.utils._getDefaultPageView (   obj,
  request 
) [private]
This is a nasty hack because the view lookup fails when it occurs too
   early in the publishing process because the request isn't marked with
   the default skin.  Explicitly marking the request appears to cause
   connection errors, so we just instantiate the view manually.

Definition at line 76 of file utils.py.

00076 
00077 def _getDefaultPageView(obj, request):
00078     """This is a nasty hack because the view lookup fails when it occurs too
00079        early in the publishing process because the request isn't marked with
00080        the default skin.  Explicitly marking the request appears to cause
00081        connection errors, so we just instantiate the view manually.
00082     """
00083     view = queryMultiAdapter((obj, request), name='default_page')
00084     if view is None:
00085         # XXX: import here to avoid a circular dependency
00086         from plone.app.layout.navigation.defaultpage import DefaultPage
00087         view = DefaultPage(obj, request)
00088     return view

Here is the caller graph for this function:

def CMFPlone.utils._getSecurity (   klass,
  create = True 
) [private]

Definition at line 649 of file utils.py.

00649 
00650 def _getSecurity(klass, create=True):
00651     # a Zope 2 class can contain some attribute that is an instance
00652     # of ClassSecurityInfo. Zope 2 scans through things looking for
00653     # an attribute that has the name __security_info__ first
00654     info = vars(klass)
00655     security = None
00656     for k, v in info.items():
00657         if hasattr(v, '__security_info__'):
00658             security = v
00659             break
00660     # Didn't found a ClassSecurityInfo object
00661     if security is None:
00662         if not create:
00663             return None
00664         # we stuff the name ourselves as __security__, not security, as this
00665         # could theoretically lead to name clashes, and doesn't matter for
00666         # zope 2 anyway.
00667         security = ClassSecurityInfo()
00668         setattr(klass, '__security__', security)
00669     return security

def CMFPlone.utils._unrestricted_rename (   container,
  id,
  new_id 
) [private]
Rename a particular sub-object

Copied from OFS.CopySupport

Less strict version of manage_renameObject:
    * no write lock check
    * no verify object check from PortalFolder so it's allowed to rename
      even unallowed portal types inside a folder

Definition at line 605 of file utils.py.

00605 
00606 def _unrestricted_rename(container, id, new_id):
00607     """Rename a particular sub-object
00608 
00609     Copied from OFS.CopySupport
00610 
00611     Less strict version of manage_renameObject:
00612         * no write lock check
00613         * no verify object check from PortalFolder so it's allowed to rename
00614           even unallowed portal types inside a folder
00615     """
00616     try:
00617         container._checkId(new_id)
00618     except:
00619         raise CopyError, MessageDialog(
00620               title='Invalid Id',
00621               message=sys.exc_info()[1],
00622               action ='manage_main')
00623     ob=container._getOb(id)
00624     if not ob.cb_isMoveable():
00625         raise CopyError, eNotSupported % escape(id)
00626     try:
00627         ob._notifyOfCopyTo(container, op=1)
00628     except:
00629         raise CopyError, MessageDialog(
00630               title='Rename Error',
00631               message=sys.exc_info()[1],
00632               action ='manage_main')
00633     container._delObject(id)
00634     ob = aq_base(ob)
00635     ob._setId(new_id)
00636 
00637     # Note - because a rename always keeps the same context, we
00638     # can just leave the ownership info unchanged.
00639     container._setObject(new_id, ob, set_owner=0)
00640     ob = container._getOb(new_id)
00641     ob._postCopy(container, op=1)
00642 
00643     return None
00644 
00645 
00646 # Copied '_getSecurity' from Archetypes.utils to avoid a dependency.

def CMFPlone.utils.base_hasattr (   obj,
  name 
)
Like safe_hasattr, but also disables acquisition.

Definition at line 461 of file utils.py.

00461 
00462 def base_hasattr(obj, name):
00463     """Like safe_hasattr, but also disables acquisition."""
00464     return safe_hasattr(aq_base(obj), name)
00465 

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.classDoesNotImplement (   class_,
  interfaces 
)

Definition at line 565 of file utils.py.

00565 
00566 def classDoesNotImplement(class_, *interfaces):
00567     # convert any Zope 2 interfaces to Zope 3 using fromZ2Interface
00568     interfaces = flatten(interfaces)
00569     normalized_interfaces = []
00570     for i in interfaces:
00571         try:
00572             i = fromZ2Interface(i)
00573         except ValueError: # already a Zope 3 interface
00574             pass
00575         assert issubclass(i, zope.interface.Interface)
00576         normalized_interfaces.append(i)
00577     implemented = implementedBy(class_)
00578     for iface in normalized_interfaces:
00579         implemented = implemented - iface
00580     return zope.interface.classImplementsOnly(class_, implemented)

Here is the call graph for this function:

def CMFPlone.utils.classImplements (   class_,
  interfaces 
)

Definition at line 552 of file utils.py.

00552 
00553 def classImplements(class_, *interfaces):
00554     # convert any Zope 2 interfaces to Zope 3 using fromZ2Interface
00555     interfaces = flatten(interfaces)
00556     normalized_interfaces = []
00557     for i in interfaces:
00558         try:
00559             i = fromZ2Interface(i)
00560         except ValueError: # already a Zope 3 interface
00561             pass
00562         assert issubclass(i, zope.interface.Interface)
00563         normalized_interfaces.append(i)
00564     return zope.interface.classImplements(class_, *normalized_interfaces)

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.context (   view)

Definition at line 61 of file utils.py.

00061 
00062 def context(view):
00063     return view.context[0]

def CMFPlone.utils.createBreadCrumbs (   context,
  request 
)

Definition at line 64 of file utils.py.

00064 
00065 def createBreadCrumbs(context, request):
00066     view = getMultiAdapter((context, request), name='breadcrumbs_view')
00067     return view.breadcrumbs()

def CMFPlone.utils.createNavTree (   context,
  request,
  sitemap = False 
)

Definition at line 68 of file utils.py.

00068 
00069 def createNavTree(context, request, sitemap=False):
00070     view = getMultiAdapter((context, request), name='navtree_builder_view')
00071     return view.navigationTree()

def CMFPlone.utils.createSiteMap (   context,
  request,
  sitemap = False 
)

Definition at line 72 of file utils.py.

00072 
00073 def createSiteMap(context, request, sitemap=False):
00074     view = getMultiAdapter((context, request), name='sitemap_builder_view')
00075     return view.siteMap()

def CMFPlone.utils.directlyProvides (   obj,
  interfaces 
)

Definition at line 539 of file utils.py.

00539 
00540 def directlyProvides(obj, *interfaces):
00541     # convert any Zope 2 interfaces to Zope 3 using fromZ2Interface
00542     interfaces = flatten(interfaces)
00543     normalized_interfaces = []
00544     for i in interfaces:
00545         try:
00546             i = fromZ2Interface(i)
00547         except ValueError: # already a Zope 3 interface
00548             pass
00549         assert issubclass(i, zope.interface.Interface)
00550         normalized_interfaces.append(i)
00551     return zope.interface.directlyProvides(obj, *normalized_interfaces)

Here is the call graph for this function:

def CMFPlone.utils.flatten (   interfaces)

Definition at line 534 of file utils.py.

00534 
00535 def flatten(interfaces):
00536     flattened = []
00537     _detuplize(interfaces, flattened.append)
00538     return tuple(flattened)

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.getDefaultPage (   obj,
  request,
  context = None 
)

Definition at line 100 of file utils.py.

00100 
00101 def getDefaultPage(obj, request, context=None):
00102     if context is not None:
00103         warnings.warn("The context parameter for getDefaultPage is "
00104                       "deprecated and will be removed in Plone 4.",
00105                       DeprecationWarning, 1)
00106     # Short circuit if we are not looking at a Folder
00107     if not obj.isPrincipiaFolderish:
00108         return None
00109     view = _getDefaultPageView(obj, request)
00110     return view.getDefaultPage()

Here is the call graph for this function:

def CMFPlone.utils.getEmptyTitle (   context,
  translated = True 
)
Returns string to be used for objects with no title or id

Definition at line 199 of file utils.py.

00199 
00200 def getEmptyTitle(context, translated=True):
00201     """Returns string to be used for objects with no title or id"""
00202     # The default is an extra fancy unicode elipsis
00203     empty = unicode('\x5b\xc2\xb7\xc2\xb7\xc2\xb7\x5d', 'utf-8')
00204     if translated:
00205         service = getGlobalTranslationService()
00206         empty = service.translate('plone', 'title_unset', context=context, default=empty)
00207     return empty

Here is the caller graph for this function:

Reads version.txt and returns version tuple

Definition at line 439 of file utils.py.

00439 
00440 def getFSVersionTuple():
00441     """Reads version.txt and returns version tuple"""
00442     vfile = "%s/version.txt" % PACKAGE_HOME
00443     v_str = open(vfile, 'r').read().lower()
00444     return versionTupleFromString(v_str)
00445 

Here is the call graph for this function:

def CMFPlone.utils.getSiteEncoding (   context)

Definition at line 173 of file utils.py.

00173 
00174 def getSiteEncoding(context):
00175     default = 'utf-8'
00176     pprop = getToolByName(context, 'portal_properties')
00177     site_props = getToolByName(pprop, 'site_properties', None)
00178     if site_props is None:
00179         return default
00180     return site_props.getProperty('default_charset', default)

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.isDefaultPage (   obj,
  request,
  context = None 
)

Definition at line 89 of file utils.py.

00089 
00090 def isDefaultPage(obj, request, context=None):
00091     if context is not None:
00092         warnings.warn("The context parameter for isDefaultPage is "
00093                       "deprecated and will be removed in Plone 4.",
00094                       DeprecationWarning, 1)
00095     container = parent(obj)
00096     if container is None:
00097         return False
00098     view = _getDefaultPageView(container, request)
00099     return view.isDefaultPage(obj)

Here is the call graph for this function:

def CMFPlone.utils.isIDAutoGenerated (   context,
  id 
)

Definition at line 111 of file utils.py.

00111 
00112 def isIDAutoGenerated(context, id):
00113     # In 2.1 non-autogenerated is the common case, caught exceptions are
00114     # expensive, so let's make a cheap check first
00115     if id.count('.') < 2:
00116         return False
00117 
00118     pt = getToolByName(context, 'portal_types')
00119     portaltypes = pt.listContentTypes()
00120     portaltypes.extend([pt.lower() for pt in portaltypes])
00121 
00122     try:
00123         parts = id.split('.')
00124         random_number = parts.pop()
00125         date_created = parts.pop()
00126         obj_type = '.'.join(parts)
00127         type = ' '.join(obj_type.split('_'))
00128         # New autogenerated ids may have a lower case portal type
00129         if ((type in portaltypes or obj_type in portaltypes) and
00130             DateTime(date_created) and
00131             float(random_number)):
00132             return True
00133     except (ValueError, AttributeError, IndexError, DateTime.DateTimeError):
00134         pass
00135 
00136     return False

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.isLinked (   obj)
check if the given content object is linked from another one
    WARNING: don't use this function in your code!!
        it is a helper for the link integrity code and will potentially
        abort the ongoing transaction, giving you unexpected results...

Definition at line 795 of file utils.py.

00795 
00796 def isLinked(obj):
00797     """ check if the given content object is linked from another one
00798         WARNING: don't use this function in your code!!
00799             it is a helper for the link integrity code and will potentially
00800             abort the ongoing transaction, giving you unexpected results...
00801     """
00802     # first check to see if link integrity handling has been enabled at all
00803     # and if so, if the removal of the object was already confirmed, i.e.
00804     # while replaying the request;  unfortunately this makes it necessary
00805     # to import from plone.app.linkintegrity here, hence the try block...
00806     try:
00807         from plone.app.linkintegrity.interfaces import ILinkIntegrityInfo
00808         info = ILinkIntegrityInfo(obj.REQUEST)
00809     except (ImportError, TypeError):
00810         # if p.a.li isn't installed the following check can be cut short...
00811         return False
00812     if not info.integrityCheckingEnabled():
00813         return False
00814     if info.isConfirmedItem(obj):
00815         return True
00816     # otherwise, when not replaying the request already, it is tried to
00817     # delete the object, making it possible to find out if it was referenced,
00818     # i.e. in case a link integrity exception was raised
00819     linked = False
00820     parent = obj.aq_inner.aq_parent
00821     try:
00822         parent.manage_delObjects(obj.getId())
00823     except OFS.ObjectManager.BeforeDeleteException, e:
00824         linked = True
00825     except: # ignore other exceptions, not useful to us at this point
00826         pass
00827     # since this function is called first thing in `delete_confirmation.cpy`
00828     # and therefore nothing can possibly have changed yet at this point, we
00829     # might as well "begin" a new transaction instead of using a savepoint,
00830     # which creates a funny exception when using zeo (see #6666)
00831     transaction.begin()
00832     return linked
00833 
00834 # BBB Plone 4.0: Cyclic import errors are bad, deprecate these import locations.
# Put these at the end to avoid an ImportError for safe_unicode
def CMFPlone.utils.lookupTranslationId (   obj,
  page,
  ids 
)

Definition at line 137 of file utils.py.

00137 
00138 def lookupTranslationId(obj, page, ids):
00139     implemented = ITranslatable.isImplementedBy(obj)
00140     if not implemented or implemented and not obj.isTranslation():
00141         pageobj = getattr(obj, page, None)
00142         if (pageobj is not None and
00143             ITranslatable.isImplementedBy(pageobj)):
00144             translation = pageobj.getTranslation()
00145             if (translation is not None and
00146                 ids.has_key(translation.getId())):
00147                 page = translation.getId()
00148     return page

Here is the caller graph for this function:

def CMFPlone.utils.normalizeString (   text,
  context = None,
  encoding = None,
  relaxed = False 
)

Definition at line 219 of file utils.py.

00219 
00220 def normalizeString(text, context=None, encoding=None, relaxed=False):
00221     assert (context is not None) or (encoding is not None), \
00222            'Either context or encoding must be provided'
00223     # Make sure we are dealing with a stringish type
00224     if not isinstance(text, basestring):
00225         # This most surely ends up in something the user does not expect
00226         # to see. But at least it does not break.
00227         text = repr(text)
00228 
00229     # Make sure we are dealing with a unicode string
00230     if not isinstance(text, unicode):
00231         if encoding is None:
00232             encoding = getSiteEncoding(context)
00233         text = unicode(text, encoding)
00234 
00235     if not relaxed:
00236         return queryUtility(IIDNormalizer).normalize(text)
00237 
00238     # BBB To be removed in Plone 4.0
00239     log_deprecated("The relaxed mode of normalizeString is deprecated and will "
00240                    "be removed in Plone 4.0. Please use either the url or file "
00241                    "name normalizer from the plone.i18n package instead.")
00242 
00243     request = getattr(context, 'REQUEST', None)
00244     # If we have a request, get the preferred user normalizer
00245     if request is not None:
00246         return IUserPreferredFileNameNormalizer(request).normalize(text)
00247 
00248     return queryUtility(IFileNameNormalizer).normalize(text)

Here is the call graph for this function:

def CMFPlone.utils.parent (   obj)

Definition at line 58 of file utils.py.

00058 
00059 def parent(obj):
00060     return aq_parent(aq_inner(obj))

Here is the caller graph for this function:

def CMFPlone.utils.portal_utf8 (   context,
  str,
  errors = 'strict' 
)

Definition at line 181 of file utils.py.

00181 
00182 def portal_utf8(context, str, errors='strict'):
00183     charset = getSiteEncoding(context)
00184     if charset.lower() in ('utf-8', 'utf8'):
00185         # Test
00186         unicode(str, 'utf-8', errors)
00187         return str
00188     else:
00189         return unicode(str, charset, errors).encode('utf-8', errors)

Here is the call graph for this function:

def CMFPlone.utils.pretty_title_or_id (   context,
  obj,
  empty_value = _marker 
)
Return the best possible title or id of an item, regardless
   of whether obj is a catalog brain or an object, but returning an
   empty title marker if the id is not set (i.e. it's auto-generated).

Definition at line 149 of file utils.py.

00149 
00150 def pretty_title_or_id(context, obj, empty_value=_marker):
00151     """Return the best possible title or id of an item, regardless
00152        of whether obj is a catalog brain or an object, but returning an
00153        empty title marker if the id is not set (i.e. it's auto-generated).
00154     """
00155     #if safe_hasattr(obj, 'aq_explicit'):
00156     #    obj = obj.aq_explicit
00157     #title = getattr(obj, 'Title', None)
00158     title = None
00159     if base_hasattr(obj, 'Title'):
00160         title = getattr(obj, 'Title', None)
00161     if safe_callable(title):
00162         title = title()
00163     if title:
00164         return title
00165     item_id = getattr(obj, 'getId', None)
00166     if safe_callable(item_id):
00167         item_id = item_id()
00168     if item_id and not isIDAutoGenerated(context, item_id):
00169         return item_id
00170     if empty_value is _marker:
00171         empty_value = getEmptyTitle(context)
00172     return empty_value

Here is the call graph for this function:

Make sure our callable checks are ConflictError safe.

Definition at line 477 of file utils.py.

00477 
00478 def safe_callable(obj):
00479     """Make sure our callable checks are ConflictError safe."""
00480     if safe_hasattr(obj, '__class__'):
00481         if safe_hasattr(obj, '__call__'):
00482             return True
00483         else:
00484             return isinstance(obj, ClassType)
00485     else:
00486         return callable(obj)
00487 

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.safe_hasattr (   obj,
  name,
  _marker = object() 
)
Make sure we don't mask exceptions like hasattr().

We don't want exceptions other than AttributeError to be masked,
since that too often masks other programming errors.
Three-argument getattr() doesn't mask those, so we use that to
implement our own hasattr() replacement.

Definition at line 466 of file utils.py.

00466 
00467 def safe_hasattr(obj, name, _marker=object()):
00468     """Make sure we don't mask exceptions like hasattr().
00469 
00470     We don't want exceptions other than AttributeError to be masked,
00471     since that too often masks other programming errors.
00472     Three-argument getattr() doesn't mask those, so we use that to
00473     implement our own hasattr() replacement.
00474     """
00475     return getattr(obj, name, _marker) is not _marker
00476 

Here is the caller graph for this function:

def CMFPlone.utils.safe_unicode (   value,
  encoding = 'utf-8' 
)
Converts a value to unicode, even it is already a unicode string.

    >>> from Products.CMFPlone.utils import safe_unicode

    >>> safe_unicode('spam')
    u'spam'
    >>> safe_unicode(u'spam')
    u'spam'
    >>> safe_unicode(u'spam'.encode('utf-8'))
    u'spam'
    >>> safe_unicode('\xc6\xb5')
    u'\u01b5'
    >>> safe_unicode(u'\xc6\xb5'.encode('iso-8859-1'))
    u'\u01b5'
    >>> safe_unicode('\xc6\xb5', encoding='ascii')
    u'\u01b5'
    >>> safe_unicode(1)
    1
    >>> print safe_unicode(None)
    None

Definition at line 488 of file utils.py.

00488 
00489 def safe_unicode(value, encoding='utf-8'):
00490     """Converts a value to unicode, even it is already a unicode string.
00491 
00492         >>> from Products.CMFPlone.utils import safe_unicode
00493 
00494         >>> safe_unicode('spam')
00495         u'spam'
00496         >>> safe_unicode(u'spam')
00497         u'spam'
00498         >>> safe_unicode(u'spam'.encode('utf-8'))
00499         u'spam'
00500         >>> safe_unicode('\xc6\xb5')
00501         u'\u01b5'
00502         >>> safe_unicode(u'\xc6\xb5'.encode('iso-8859-1'))
00503         u'\u01b5'
00504         >>> safe_unicode('\xc6\xb5', encoding='ascii')
00505         u'\u01b5'
00506         >>> safe_unicode(1)
00507         1
00508         >>> print safe_unicode(None)
00509         None
00510     """
00511     if isinstance(value, unicode):
00512         return value
00513     elif isinstance(value, basestring):
00514         try:
00515             value = unicode(value, encoding)
00516         except (UnicodeDecodeError):
00517             value = value.decode('utf-8', 'replace')
00518     return value
00519 

Here is the caller graph for this function:

def CMFPlone.utils.safeToInt (   value)
Convert value to integer or just return 0 if we can't

Definition at line 395 of file utils.py.

00395 
00396 def safeToInt(value):
00397     """Convert value to integer or just return 0 if we can't"""
00398     try:
00399         return int(value)
00400     except ValueError:
00401         return 0

Here is the caller graph for this function:

def CMFPlone.utils.scale_image (   image_file,
  max_size = None,
  default_format = None 
)
Scales an image down to at most max_size preserving aspect ratio
from an input file

    >>> import Products.CMFPlone
    >>> import os
    >>> from StringIO import StringIO
    >>> from Products.CMFPlone.utils import scale_image
    >>> from PIL import Image

Let's make a couple test images and see how it works (all are
100x100), the gif is palletted mode::

    >>> plone_path = os.path.dirname(Products.CMFPlone.__file__)
    >>> pjoin = os.path.join
    >>> path = pjoin(plone_path, 'tests', 'images')
    >>> orig_jpg = open(pjoin(path, 'test.jpg'), 'rb')
    >>> orig_png = open(pjoin(path, 'test.png'), 'rb')
    >>> orig_gif = open(pjoin(path, 'test.gif'), 'rb')

We'll also make some evil non-images, including one which
masquerades as a jpeg (which would trick OFS.Image)::

    >>> invalid = StringIO('<div>Evil!!!</div>')
    >>> sneaky = StringIO('\377\330<div>Evil!!!</div>')

OK, let's get to it, first check that our bad images fail:

    >>> scale_image(invalid, (50, 50))
    Traceback (most recent call last):
    ...
    IOError: cannot identify image file
    >>> scale_image(sneaky, (50, 50))
    Traceback (most recent call last):
    ...
    IOError: cannot identify image file

Now that that's out of the way we check on our real images to make
sure the format and mode are preserved, that they are scaled, and that they
return the correct mimetype::

    >>> new_jpg, mimetype = scale_image(orig_jpg, (50, 50))
    >>> img = Image.open(new_jpg)
    >>> img.size
    (50, 50)
    >>> img.format
    'JPEG'
    >>> mimetype
    'image/jpeg'

    >>> new_png, mimetype = scale_image(orig_png, (50, 50))
    >>> img = Image.open(new_png)
    >>> img.size
    (50, 50)
    >>> img.format
    'PNG'
    >>> mimetype
    'image/png'

    >>> new_gif, mimetype = scale_image(orig_gif, (50, 50))
    >>> img = Image.open(new_gif)
    >>> img.size
    (50, 50)
    >>> img.format
    'GIF'
    >>> img.mode
    'P'
    >>> mimetype
    'image/gif'

We should also preserve the aspect ratio by scaling to the given
width only unless told not to (we need to reset out files before
trying again though::

    >>> orig_jpg.seek(0)
    >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 100))
    >>> img = Image.open(new_jpg)
    >>> img.size
    (70, 70)

    >>> orig_jpg.seek(0)
    >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 50))
    >>> img = Image.open(new_jpg)
    >>> img.size
    (50, 50)

Definition at line 670 of file utils.py.

00670 
00671 def scale_image(image_file, max_size=None, default_format=None):
00672     """Scales an image down to at most max_size preserving aspect ratio
00673     from an input file
00674 
00675         >>> import Products.CMFPlone
00676         >>> import os
00677         >>> from StringIO import StringIO
00678         >>> from Products.CMFPlone.utils import scale_image
00679         >>> from PIL import Image
00680 
00681     Let's make a couple test images and see how it works (all are
00682     100x100), the gif is palletted mode::
00683 
00684         >>> plone_path = os.path.dirname(Products.CMFPlone.__file__)
00685         >>> pjoin = os.path.join
00686         >>> path = pjoin(plone_path, 'tests', 'images')
00687         >>> orig_jpg = open(pjoin(path, 'test.jpg'), 'rb')
00688         >>> orig_png = open(pjoin(path, 'test.png'), 'rb')
00689         >>> orig_gif = open(pjoin(path, 'test.gif'), 'rb')
00690 
00691     We'll also make some evil non-images, including one which
00692     masquerades as a jpeg (which would trick OFS.Image)::
00693 
00694         >>> invalid = StringIO('<div>Evil!!!</div>')
00695         >>> sneaky = StringIO('\377\330<div>Evil!!!</div>')
00696 
00697     OK, let's get to it, first check that our bad images fail:
00698 
00699         >>> scale_image(invalid, (50, 50))
00700         Traceback (most recent call last):
00701         ...
00702         IOError: cannot identify image file
00703         >>> scale_image(sneaky, (50, 50))
00704         Traceback (most recent call last):
00705         ...
00706         IOError: cannot identify image file
00707 
00708     Now that that's out of the way we check on our real images to make
00709     sure the format and mode are preserved, that they are scaled, and that they
00710     return the correct mimetype::
00711 
00712         >>> new_jpg, mimetype = scale_image(orig_jpg, (50, 50))
00713         >>> img = Image.open(new_jpg)
00714         >>> img.size
00715         (50, 50)
00716         >>> img.format
00717         'JPEG'
00718         >>> mimetype
00719         'image/jpeg'
00720 
00721         >>> new_png, mimetype = scale_image(orig_png, (50, 50))
00722         >>> img = Image.open(new_png)
00723         >>> img.size
00724         (50, 50)
00725         >>> img.format
00726         'PNG'
00727         >>> mimetype
00728         'image/png'
00729 
00730         >>> new_gif, mimetype = scale_image(orig_gif, (50, 50))
00731         >>> img = Image.open(new_gif)
00732         >>> img.size
00733         (50, 50)
00734         >>> img.format
00735         'GIF'
00736         >>> img.mode
00737         'P'
00738         >>> mimetype
00739         'image/gif'
00740 
00741     We should also preserve the aspect ratio by scaling to the given
00742     width only unless told not to (we need to reset out files before
00743     trying again though::
00744 
00745         >>> orig_jpg.seek(0)
00746         >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 100))
00747         >>> img = Image.open(new_jpg)
00748         >>> img.size
00749         (70, 70)
00750 
00751         >>> orig_jpg.seek(0)
00752         >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 50))
00753         >>> img = Image.open(new_jpg)
00754         >>> img.size
00755         (50, 50)
00756 
00757     """
00758     if max_size is None:
00759         max_size = IMAGE_SCALE_PARAMS['scale']
00760     if default_format is None:
00761         default_format = IMAGE_SCALE_PARAMS['default_format']
00762     # Make sure we have ints
00763     size = (int(max_size[0]), int(max_size[1]))
00764     # Load up the image, don't try to catch errors, we want to fail miserably
00765     # on invalid images
00766     image = Image.open(image_file)
00767     # When might image.format not be true?
00768     format = image.format
00769     mimetype = 'image/%s'%format.lower()
00770     cur_size = image.size
00771     # from Archetypes ImageField
00772     # consider image mode when scaling
00773     # source images can be mode '1','L,','P','RGB(A)'
00774     # convert to greyscale or RGBA before scaling
00775     # preserve palletted mode (but not pallette)
00776     # for palletted-only image formats, e.g. GIF
00777     # PNG compression is OK for RGBA thumbnails
00778     original_mode = image.mode
00779     if original_mode == '1':
00780         image = image.convert('L')
00781     elif original_mode == 'P':
00782         image = image.convert('RGBA')
00783     # Rescale in place with an method that will not alter the aspect ratio
00784     # and will only shrink the image not enlarge it.
00785     image.thumbnail(size, resample=IMAGE_SCALE_PARAMS['algorithm'])
00786     # preserve palletted mode for GIF and PNG
00787     if original_mode == 'P' and format in ('GIF', 'PNG'):
00788         image = image.convert('P')
00789     # Save
00790     new_file = StringIO()
00791     image.save(new_file, format, quality=IMAGE_SCALE_PARAMS['quality'])
00792     new_file.seek(0)
00793     # Return the file data and the new mimetype
00794     return new_file, mimetype

Here is the caller graph for this function:

Write human legible note

Definition at line 446 of file utils.py.

00446 
00447 def transaction_note(note):
00448     """Write human legible note"""
00449     T=transaction.get()
00450     if isinstance(note, unicode):
00451         # Convert unicode to a regular string for the backend write IO.
00452         # UTF-8 is the only reasonable choice, as using unicode means
00453         # that Latin-1 is probably not enough.
00454         note = note.encode('utf-8', 'replace')
00455 
00456     if (len(T.description)+len(note))>=65535:
00457         log('Transaction note too large omitting %s' % str(note))
00458     else:
00459         T.note(str(note))
00460 

def CMFPlone.utils.tuplize (   value)

Definition at line 520 of file utils.py.

00520 
00521 def tuplize(value):
00522     if isinstance(value, tuple):
00523         return value
00524     if isinstance(value, list):
00525         return tuple(value)
00526     return (value,)

def CMFPlone.utils.typesToList (   context)

Definition at line 208 of file utils.py.

00208 
00209 def typesToList(context):
00210     ntp = getToolByName(context, 'portal_properties').navtree_properties
00211     ttool = getToolByName(context, 'portal_types')
00212     bl = ntp.getProperty('metaTypesNotToList', ())
00213     bl_dict = {}
00214     for t in bl:
00215         bl_dict[t] = 1
00216     all_types = ttool.listContentTypes()
00217     wl = [t for t in all_types if not bl_dict.has_key(t)]
00218     return wl

Here is the call graph for this function:

def CMFPlone.utils.utf8_portal (   context,
  str,
  errors = 'strict' 
)

Definition at line 190 of file utils.py.

00190 
00191 def utf8_portal(context, str, errors='strict'):
00192     charset = getSiteEncoding(context)
00193     if charset.lower() in ('utf-8', 'utf8'):
00194         # Test
00195         unicode(str, 'utf-8', errors)
00196         return str
00197     else:
00198         return unicode(str, 'utf-8', errors).encode(charset, errors)

Here is the call graph for this function:

Returns version tuple from passed in version string

    >>> versionTupleFromString('1.2.3')
    (1, 2, 3, 'final', 0)

    >>> versionTupleFromString('2.1-final1 (SVN)')
    (2, 1, 0, 'final', 1)

    >>> versionTupleFromString('3-beta')
    (3, 0, 0, 'beta', 0)

    >>> versionTupleFromString('2.0a3')
    (2, 0, 0, 'alpha', 3)

    >>> versionTupleFromString('foo') is None
    True

Definition at line 405 of file utils.py.

00405 
00406 def versionTupleFromString(v_str):
00407     """Returns version tuple from passed in version string
00408 
00409         >>> versionTupleFromString('1.2.3')
00410         (1, 2, 3, 'final', 0)
00411 
00412         >>> versionTupleFromString('2.1-final1 (SVN)')
00413         (2, 1, 0, 'final', 1)
00414 
00415         >>> versionTupleFromString('3-beta')
00416         (3, 0, 0, 'beta', 0)
00417 
00418         >>> versionTupleFromString('2.0a3')
00419         (2, 0, 0, 'alpha', 3)
00420 
00421         >>> versionTupleFromString('foo') is None
00422         True
00423         """
00424     regex_str = "(^\d+)[.]?(\d*)[.]?(\d*)[- ]?(alpha|beta|candidate|final|a|b|rc)?(\d*)"
00425     v_regex = re.compile(regex_str)
00426     match = v_regex.match(v_str)
00427     if match is None:
00428         v_tpl = None
00429     else:
00430         groups = list(match.groups())
00431         for i in (0, 1, 2, 4):
00432             groups[i] = safeToInt(groups[i])
00433         if groups[3] is None:
00434             groups[3] = 'final'
00435         elif groups[3] in rl_abbr.keys():
00436             groups[3] = rl_abbr[groups[3]]
00437         v_tpl = tuple(groups)
00438     return v_tpl

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFPlone.utils.webdav_enabled (   obj,
  container 
)
WebDAV check used in externalEditorEnabled.py

Definition at line 581 of file utils.py.

00581 
00582 def webdav_enabled(obj, container):
00583     """WebDAV check used in externalEditorEnabled.py"""
00584 
00585     # Object implements lock interface
00586     interface_tool = getToolByName(container, 'portal_interface')
00587     if not interface_tool.objectImplements(obj, 'webdav.WriteLockInterface.WriteLockInterface'):
00588         return False
00589 
00590     # Backwards compatibility code for AT < 1.3.6
00591     if safe_hasattr(obj, '__dav_marshall__'):
00592         if obj.__dav_marshall__ == False:
00593             return False
00594     return True
00595 
00596 
00597 # Copied 'unrestricted_rename' from ATCT migrations to avoid
00598 # a dependency.

Here is the call graph for this function:


Variable Documentation

Definition at line 50 of file utils.py.

Initial value:
00001 {'scale': MEMBER_IMAGE_SCALE,
00002                       'quality': PIL_QUALITY,
00003                       'algorithm': PIL_SCALING_ALGO,
00004                       'default_format': 'PNG'}

Definition at line 45 of file utils.py.

Definition at line 44 of file utils.py.

tuple CMFPlone.utils.PACKAGE_HOME = Globals.package_home(globals())

Definition at line 33 of file utils.py.

Definition at line 43 of file utils.py.

Definition at line 42 of file utils.py.

tuple CMFPlone.utils.release_levels = ('alpha', 'beta', 'candidate', 'final')

Definition at line 402 of file utils.py.

dictionary CMFPlone.utils.rl_abbr = {'a':'alpha', 'b':'beta', 'rc':'candidate'}

Definition at line 403 of file utils.py.

tuple CMFPlone.utils.WWW_DIR = join(PACKAGE_HOME, 'www')

Definition at line 34 of file utils.py.