title: Plone, Archetypes: Change a TextField from text/plain to text/html
body: <p>I have a family of Plone sites which use Archetypes-based contents.</p>
  
  <p>I have some <code>TextField</code>s which need to be changed from <code>text/plain</code> to <code>text/html</code>; say, the schema snipped</p>
  
  <pre><code>TextField(
        name='summary',
        default='',
        read_permission=Access_contents_information,
        default_content_type='text/plain',
        allowable_content_types=('text/plain',),
        storage=AnnotationStorage(migrate=True),
        widget=TextAreaWidget(
            label=_('my_label_summary',
                    default='Summary'),
            i18n_domain='plone',
        ),
    ),
  </code></pre>
  
  <p>should change to something like</p>
  
  <pre><code>TextField(
        name='summary',
        default='',
        read_permission=Access_contents_information,
        default_content_type='text/html',
        default_output_type='text/html',
        allowable_content_types=('text/html',),
        storage=AnnotationStorage(migrate=True),
        widget=RichWidget(
            label=_('my_label_summary',
                    default='Summary'),
            i18n_domain='plone',
        ),
    ),
  </code></pre>
  
  <p>Since the number of objects is small, I'd be willing to accept a temporary ugly appearance of the affected fields (e.g. collapsed linebreaks); more important is to have the visual editor (which doesn't work for me with switchable content types).</p>
  
  <p>The best solution would of course be to have the current <code>text/plain</code> fields used as they are, and when about to edit the object, have them converted to a reasonable <code>text/html</code> equivalent, which can then be edited nicely with the visual editor (CKEditor, in my case).</p>
  
  <p>However, if I simply edit the object with the changed schema, the visual editor looks fine, but the stored text is surrounded by <code>&lt;p&gt;</code> / <code>&lt;/p&gt;</code> tags and interpreted as <code>text/plain</code>.</p>
  
  <p>I found <code>/archetype_tool/manage_updateSchemaForm</code>, but updating the schema for my class there didn't help.</p>
  
  <p>I found <a href="https://plone.org/products/archetypes/documentation/old/ArchetypesDeveloperGuide/" rel="nofollow">https://plone.org/products/archetypes/documentation/old/ArchetypesDeveloperGuide/</a>, but this looks both incomplete and outdated.</p>
  
  <p>Any pointers? Thank you!</p>
  
  <p><strong>Update:</strong></p>
  
  <p>Since this won't fit in a comment:
  I have created an <code>upgrades</code> subpackage now; <code>configure.zcml</code>:</p>
  
  <pre><code>&lt;configure
      xmlns="http://namespaces.zope.org/zope"
      xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
      i18n_domain="plone"&gt;
  
      &lt;genericsetup:upgradeStep
          source="*"
          destination="1001"
          title="text/html fields for MyType"
          profile="Products.myproduct:default"
          handler=".to_1001.fix_mimetypes"/&gt;
  
  &lt;/configure&gt;
  </code></pre>
  
  <p>Module code (<code>to_1001.py</code>):</p>
  
  <pre><code>import logging
  from Products.CMFCore.utils import getToolByName
  from ..tools.log import getLogSupport
  
  logger, debug_active, DEBUG = getLogSupport(fn=__file__)
  
  def htmlify_attribute(o, attr_name, brain=None, default=u''):
      """
      Change MIME type of a TextField to text/html
      """
      attr = getattr(o, attr_name, None)
      changed = False
  
      brain_url = (brain is not None
                   and brain.getURL()
                   or None)
      if not attr:
          mutator = o.getField(attr_name).getMutator(o)
          mutator(default)
          attr = getattr(o, attr_name, None)
          changed = True
  
      convert = False
      mimetype = getattr(attr, 'mimetype', 'text/plain')
      if mimetype != 'text/html':
          if brain_url is not None:
              logger.info('Fixing MIME type of %(attr_name)s'
                          ' for %(brain_url)s', locals())
          setattr(attr, 'mimetype', 'text/html')
          changed = True
  
      return changed
  
  def fix_mimetypes(context):
      """
      text/plain --&gt; text/html for some MyType fields
      """
      pc = getToolByName(context, 'portal_catalog')
      TYPES = ['MyType']
      brains = pc.unrestrictedSearchResults(portal_type=TYPES)
      total = len(brains)
      MASK = 'Fixing MIME types for %(total)d %(TYPES)s objects'
      logger.info(MASK + ' ...', locals())
      cnt = 0
  
      import pdb; pdb.set_trace()
      for brain in brains:
          obj = brain.getObject()
          if htmlify_attribute(obj, 'summary', brain):
              cnt += 1
  
      if cnt or True:
          logger.info('%(cnt)d objects changed', locals())
      logger.info(MASK + ': DONE', locals())
      return ('Done '+MASK) % locals()
  </code></pre>
  
  <p>Since my product lacked a <a href="http://docs.plone.org/4/en/develop/addons/components/genericsetup.html#increment-profile-version" rel="nofollow">special profile version</a>, I created a <code>.../profiles/default/metadata.xml</code> file and set a value of <code>1000</code>; since nothing happened on startup and nothing special could be observed in the QuickInstaller, I re-installed, and then increased the number by one.</p>
  
  <p>My <code>to_1001</code> module is imported on startup, as I can see by the registration of a logger
  (which is logged); but it is not <em>used</em> (as I know because of
  <code>pdb.set_trace()</code>), neither when starting up (<code>bin/instance fg</code>) with an increased version number nor when re-installing in the QuickInstaller.</p>
  
  <p>What is missing?
  How is this upgrade step supposed to work, i.e. to be triggered?</p>