Changeset 1446 in products


Ignore:
Timestamp:
Dec 8, 2009 7:53:25 AM (14 years ago)
Author:
piv
Message:

merge from plone 2.1 branch: r2465-2483

Location:
quintagroup.transmogrifier/trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • quintagroup.transmogrifier/trunk

    • Property svn:mergeinfo changed from /quintagroup.transmogrifier/branches/plone-2.1/quintagroup.transmogrifier:1387-1389,1394-1413 to /quintagroup.transmogrifier/branches/plone-2.1/quintagroup.transmogrifier:1387-1389,1394-1413,1426-1444
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/adapters/exporting.py

    r460 r1446  
    1010from Products.Archetypes import config as atcfg 
    1111 
     12from collective.transmogrifier.interfaces import ITransmogrifier 
     13 
    1214from quintagroup.transmogrifier.interfaces import IExportDataCorrector 
    1315 
     
    1618    """ 
    1719    implements(IExportDataCorrector) 
    18     adapts(IBaseObject) 
     20    adapts(IBaseObject, ITransmogrifier) 
    1921 
    20     def __init__(self, context): 
     22    def __init__(self, context, transmogrifier): 
    2123        self.context = context 
     24        self.transmogrifier = transmogrifier 
    2225 
    2326    def __call__(self, data): 
     
    5760 
    5861    implements(IExportDataCorrector) 
    59     adapts(IATTopicCriterion) 
     62    adapts(IATTopicCriterion, ITransmogrifier) 
    6063 
    61     def __init__(self, context): 
     64    def __init__(self, context, transmogrifier): 
    6265        self.context = context 
     66        self.transmogrifier = transmogrifier 
    6367        self.marshaller = getComponent('atxml') 
    6468 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/adapters/importing.py

    r460 r1446  
    77from Products.Archetypes.interfaces import IBaseObject 
    88from Products.Archetypes import atapi 
     9 
     10from collective.transmogrifier.interfaces import ITransmogrifier 
    911 
    1012from quintagroup.transmogrifier.interfaces import IImportDataCorrector 
     
    1719    """ 
    1820    implements(IImportDataCorrector) 
    19     adapts(IBaseObject) 
     21    adapts(IBaseObject, ITransmogrifier) 
    2022 
    21     def __init__(self, context): 
     23    def __init__(self, context, transmogrifier): 
    2224        self.context = context 
     25        self.transmogrifier = transmogrifier 
    2326 
    2427    def __call__(self, data): 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/binary.py

    r1414 r1446  
    99 
    1010from collective.transmogrifier.interfaces import ISection, ISectionBlueprint 
    11 from collective.transmogrifier.utils import defaultMatcher 
     11from collective.transmogrifier.utils import defaultMatcher, Condition 
    1212 
    1313class FileExporterSection(object): 
     
    2424        #self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_fields') 
    2525        self.excludekey = options.get('exclude-key', '_excluded_fields').strip() 
    26          
     26 
     27        self.exclude_fieldtypes = filter(None, [i.strip() for i in 
     28                                         options.get('exclude-fieldtypes', '').splitlines()]) 
    2729        self.doc = minidom.Document() 
     30        self.condition = Condition(options.get('condition', 'python:True'), 
     31                                   transmogrifier, name, options) 
    2832 
    2933    def __iter__(self): 
     
    4549                for field in schema.keys(): 
    4650                    if obj.isBinary(field): 
     51                        binary_field_names.append(field) 
     52                        if not self.condition(item, context=obj, fname=field): 
     53                            continue 
    4754                        fname, ct, data = self.extractFile(obj, field) 
    48                         binary_field_names.append(field) 
    4955                        if fname == '' or data == '': 
    5056                            # empty file fields have empty filename and empty data 
     
    139145        self.contextkey = defaultMatcher(options, 'context-key', name, 'import_context') 
    140146 
     147        self.condition = Condition(options.get('condition', 'python:True'), 
     148                                   transmogrifier, name, options) 
     149 
    141150    def __iter__(self): 
    142151        for item in self.previous: 
     
    167176                            if data is None: 
    168177                                continue 
     178                        if not self.condition(item, context=obj, fname=field, 
     179                            filename=fname, data=data, mimetype=ct): 
     180                            continue 
    169181                        mutator = obj.getField(field).getMutator(obj) 
    170182                        mutator(data, filename=fname, mimetype=ct) 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/binary.txt

    r453 r1446  
    1717section. 
    1818 
     19Also this section provides condition option which, if specified, exports/imports 
     20this or another binary field only if condition expression evaluates to true. 
     21 
    1922>>> import pprint 
    2023>>> binary = """ 
     
    3235... [fileexporter] 
    3336... blueprint = quintagroup.transmogrifier.fileexporter 
     37... condition = python:fname != 'image' 
    3438...  
    3539... [dataprinter] 
     
    5862                            'name': '.file-fields.xml'}}, 
    5963 '_path': 'spam/eggs/foo'} 
    60 <?xml version="1.0" ?> 
     64<?xml version="1.0" encoding="utf-8"?> 
    6165<manifest> 
    6266  <field name="file"> 
    63     <filename>archive.tar.gz</filename> 
    64     <mimetype>application/x-tar</mimetype> 
     67    <filename> 
     68      archive.tar.gz 
     69    </filename> 
     70    <mimetype> 
     71      application/x-tar 
     72    </mimetype> 
    6573  </field> 
    6674</manifest> 
     
    7078 
    7179TODO: write test for getting data for fields from import context 
     80 
     81The ``condition`` expression hass access to the following: 
     82 
     83=================== ========================================================== 
     84 ``item``            the current pipeline item 
     85 ``transmogrifier``  the transmogrifier 
     86 ``name``            the name of the splitter section 
     87 ``options``         the splitter options 
     88 ``modules``         sys.modules 
     89 ``context``         the current content object 
     90 ``fname``           the name of the field being processed 
     91 ``filename``        the file name binary field is loaded into (import only) 
     92 ``data``            data read from the file (import only) 
     93 ``mimetype``        data mimetype (import only) 
     94=================== ========================================================== 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/datacorrector.py

    r277 r1446  
    11from zope.interface import classProvides, implements 
    2 from zope.component import queryAdapter 
     2from zope.component import queryMultiAdapter 
    33 
    44from collective.transmogrifier.interfaces import ISection, ISectionBlueprint 
     
    1414    def __init__(self, transmogrifier, name, options, previous): 
    1515        self.previous = previous 
     16        self.transmogrifier = transmogrifier 
    1617        self.context = transmogrifier.context 
    1718 
     
    5253                if not name in file_store: 
    5354                    continue 
    54                 adapter = queryAdapter(obj, self.interface, name) 
     55                adapter = queryMultiAdapter((obj, self.transmogrifier), 
     56                                            self.interface, name) 
    5557                if adapter: 
    5658                    file_store[name] = adapter(file_store[name]) 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/exportimport.py

    r1416 r1446  
     1# -*- coding: utf-8 -*- 
    12import os 
    23import tempfile 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/manifest.txt

    r1240 r1446  
    6060                         'name': '.objects.xml'}}, 
    6161 '_path': ''} 
    62 <?xml version="1.0" ?> 
     62<?xml version="1.0" encoding="utf-8"?> 
    6363<manifest> 
    64   <record type="Folder">news</record> 
    65   <record type="Folder">events</record> 
    66   <record type="Document">front-page</record> 
    67   <record type="Document">only-in-manifest</record> 
     64  <record type="Folder"> 
     65    news 
     66  </record> 
     67  <record type="Folder"> 
     68    events 
     69  </record> 
     70  <record type="Document"> 
     71    front-page 
     72  </record> 
     73  <record type="Document"> 
     74    only-in-manifest 
     75  </record> 
    6876</manifest> 
    6977<BLANKLINE> 
     
    7381 '_path': 'news', 
    7482 '_type': 'Folder'} 
    75 <?xml version="1.0" ?> 
     83<?xml version="1.0" encoding="utf-8"?> 
    7684<manifest> 
    77   <record type="Topic">aggregator</record> 
    78   <record type="File">once-more</record> 
     85  <record type="Topic"> 
     86    aggregator 
     87  </record> 
     88  <record type="File"> 
     89    once-more 
     90  </record> 
    7991</manifest> 
    8092<BLANKLINE> 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/propertymanager.py

    r453 r1446  
     1from copy import deepcopy 
    12from xml.dom import minidom 
    23 
     
    1415        NodeAdapterBase class. 
    1516    """ 
     17     
     18    _encoding = 'utf-8' 
     19     
    1620    def __init__(self): 
    1721        pass 
     
    2933        return text 
    3034 
     35    def _extractProperties(self): 
     36        fragment = self._doc.createDocumentFragment() 
     37 
     38        for prop_map in self.context._propertyMap(): 
     39            prop_id = prop_map['id'] 
     40            if prop_id == 'i18n_domain': 
     41                continue 
     42 
     43            # Don't export read-only nodes 
     44            if 'w' not in prop_map.get('mode', 'wd'): 
     45                continue 
     46 
     47            node = self._doc.createElement('property') 
     48            node.setAttribute('name', prop_id) 
     49 
     50            prop = self.context.getProperty(prop_id) 
     51            if isinstance(prop, (tuple, list)): 
     52                for value in prop: 
     53                    if isinstance(value, str): 
     54                        value = value.decode(self._encoding) 
     55                    child = self._doc.createElement('element') 
     56                    child.appendChild(self._doc.createTextNode(value)) 
     57                    node.appendChild(child) 
     58            else: 
     59                if prop_map.get('type') == 'boolean': 
     60                    prop = unicode(bool(prop)) 
     61                elif isinstance(prop, str): 
     62                    prop = prop.decode(self._encoding) 
     63                elif not isinstance(prop, basestring): 
     64                    prop = unicode(prop) 
     65                child = self._doc.createTextNode(prop) 
     66                node.appendChild(child) 
     67 
     68            if 'd' in prop_map.get('mode', 'wd') and not prop_id == 'title': 
     69                prop_type = prop_map.get('type', 'string') 
     70                node.setAttribute('type', unicode(prop_type)) 
     71                select_variable = prop_map.get('select_variable', None) 
     72                if select_variable is not None: 
     73                    node.setAttribute('select_variable', select_variable) 
     74 
     75            if hasattr(self, '_i18n_props') and prop_id in self._i18n_props: 
     76                node.setAttribute('i18n:translate', '') 
     77 
     78            fragment.appendChild(node) 
     79 
     80        return fragment 
     81 
     82    def _initProperties(self, node): 
     83        obj = self.context 
     84        if node.hasAttribute('i18n:domain'): 
     85            i18n_domain = str(node.getAttribute('i18n:domain')) 
     86            obj._updateProperty('i18n_domain', i18n_domain) 
     87        for child in node.childNodes: 
     88            if child.nodeName != 'property': 
     89                continue 
     90            prop_id = str(child.getAttribute('name')) 
     91            prop_map = obj.propdict().get(prop_id, None) 
     92 
     93            if prop_map is None: 
     94                if child.hasAttribute('type'): 
     95                    val = str(child.getAttribute('select_variable')) 
     96                    prop_type = str(child.getAttribute('type')) 
     97                    obj._setProperty(prop_id, val, prop_type) 
     98                    prop_map = obj.propdict().get(prop_id, None) 
     99                else: 
     100                    raise ValueError("undefined property '%s'" % prop_id) 
     101 
     102            if not 'w' in prop_map.get('mode', 'wd'): 
     103                raise BadRequest('%s cannot be changed' % prop_id) 
     104 
     105            elements = [] 
     106            remove_elements = [] 
     107            for sub in child.childNodes: 
     108                if sub.nodeName == 'element': 
     109                    if len(sub.childNodes) > 0: 
     110                        value = sub.childNodes[0].nodeValue 
     111                        if isinstance(value, unicode): 
     112                            value = value.encode(self._encoding) 
     113                        if self._convertToBoolean(sub.getAttribute('remove') 
     114                                                  or 'False'): 
     115                            remove_elements.append(value) 
     116                            if value in elements: 
     117                                elements.remove(value) 
     118                        else: 
     119                            elements.append(value) 
     120                            if value in remove_elements: 
     121                                remove_elements.remove(value) 
     122 
     123            if elements or prop_map.get('type') == 'multiple selection': 
     124                prop_value = tuple(elements) or () 
     125            elif prop_map.get('type') == 'boolean': 
     126                prop_value = self._convertToBoolean(self._getNodeText(child)) 
     127            else: 
     128                # if we pass a *string* to _updateProperty, all other values 
     129                # are converted to the right type 
     130                prop_value = self._getNodeText(child).encode(self._encoding) 
     131 
     132            if not self._convertToBoolean(child.getAttribute('purge') 
     133                                          or 'True'): 
     134                # If the purge attribute is False, merge sequences 
     135                prop = obj.getProperty(prop_id) 
     136                if isinstance(prop, (tuple, list)): 
     137                    prop_value = (tuple([p for p in prop 
     138                                         if p not in prop_value and 
     139                                            p not in remove_elements]) + 
     140                                  tuple(prop_value)) 
     141 
     142            obj._updateProperty(prop_id, prop_value) 
     143 
    31144class PropertiesExporterSection(object): 
    32145    classProvides(ISectionBlueprint) 
     
    76189                        continue 
    77190                    if elem.getAttribute('name') not in excluded_props: 
    78                         node.appendChild(elem) 
     191                        node.appendChild(deepcopy(elem)) 
    79192                if node.hasChildNodes(): 
    80193                    doc.appendChild(node) 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/sitewalker.py

    r415 r1446  
    33 
    44from collective.transmogrifier.interfaces import ISection, ISectionBlueprint 
     5from collective.transmogrifier.utils import Condition 
    56 
    67from Products.CMFCore.interfaces import IFolderish 
     
    2324        self.storage = self.anno.setdefault(VALIDATIONKEY, []) 
    2425 
     26        self.condition = Condition(options.get('condition', 'python:True'), 
     27                                   transmogrifier, name, options) 
     28 
     29    def getContained(self, obj): 
     30        contained = [(k, v) for k, v in obj.contentItems() 
     31                        if self.condition(None, context=v)] 
     32        return tuple(contained) 
     33 
    2534    def walk(self, obj): 
    2635        if IFolderish.providedBy(obj) or IBaseFolder.providedBy(obj): 
    27             contained = [(k, v.getPortalTypeName()) for k, v in obj.contentItems()] 
    28             yield obj, tuple(contained) 
    29             for v in obj.contentValues(): 
     36            contained = self.getContained(obj) 
     37            yield obj, tuple([(k, v.getPortalTypeName()) for k, v in contained]) 
     38            for k, v in contained: 
    3039                for x in self.walk(v): 
    3140                    yield x 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/sitewalker.txt

    r275 r1446  
    1111pairs of contained items. 
    1212 
     13You can also specify an optional ``condition`` option; if given, content object 
     14is going into pipeline only if the condition, which is also a TALES is true. 
     15 
    1316>>> sitewalker = """ 
    1417... [transmogrifier] 
     
    1922... [sitewalker] 
    2023... blueprint = quintagroup.transmogrifier.sitewalker 
    21 ...  
     24... condition = python:context.getPortalTypeName() not in ('File', 'Image') 
     25... 
    2226... [printer] 
    2327... blueprint = collective.transmogrifier.sections.tests.pprinter 
     
    3842{'_type': 'Document', '_path': 'folder1/document2'} 
    3943{'_type': 'Document', '_path': 'document3'} 
     44 
     45 
     46The ``condition`` expression has an access to the following: 
     47 
     48=================== ========================================================== 
     49 ``context``         the current content object 
     50 ``transmogrifier``  the transmogrifier 
     51 ``name``            the name of the splitter section 
     52 ``options``         the splitter options 
     53 ``modules``         sys.modules 
     54=================== ========================================================== 
  • quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/tests.py

    r1381 r1446  
    485485    test.globs['transmogrifier'].context = test.globs['plone'] 
    486486 
     487    from collective.transmogrifier.interfaces import ITransmogrifier 
    487488    from quintagroup.transmogrifier.interfaces import IExportDataCorrector, \ 
    488489        IImportDataCorrector 
     
    490491    class MockExportAdapter(object): 
    491492        implements(IExportDataCorrector) 
    492         adapts(MockPortal) 
    493         def __init__(self, context): 
     493        adapts(MockPortal, ITransmogrifier) 
     494        def __init__(self, context, transmogrifier): 
    494495            self.context = context 
     496            self.transmogrifier = transmogrifier 
    495497 
    496498        def __call__(self, data): 
     
    501503    class MockImportAdapter(object): 
    502504        implements(IImportDataCorrector) 
    503         adapts(MockPortal) 
    504         def __init__(self, context): 
     505        adapts(MockPortal, ITransmogrifier) 
     506        def __init__(self, context, transmogrifier): 
    505507            self.context = context 
     508            self.transmogrifier = transmogrifier 
    506509 
    507510        def __call__(self, data): 
     
    810813                return 'binary data' 
    811814            else: 
    812                 return '' 
     815                return 'image' 
    813816 
    814817        def getMutator(self, obj): 
Note: See TracChangeset for help on using the changeset viewer.