• Last modified Aug. 1, 2012, 4:03 p.m.
    Posted July 31, 2012, 4:43 p.m. by admin

    After recently upgrading a site from Plone 3 to Plone 4 I noticed that when visiting the portal_view_customizations page was spitting an AttributeError.

    Easily fixed I thought. Apparently not so.

    I got there after a couple of hours digging in debug mode. Here's my solution:

    The error I was getting form Plone was:

    AttributeError: type object 'IThemeQPloneSkinLite' has no attribute 'isOrExtends'
    

    This is a product that was already uninstalled. To fix the issue I had to place the original qPloneSkinLite product in the products directory.

    Then start up a Zope debug session:

    # ./bin/instance debug
    

    Execute the following code, replacing PORTAL with the path to your Plone portal relative to the Zope root.

    sm = app.PORTAL.getSiteManager()
    adapters = sm.registeredAdapters()
    
    for reg in adapters:
        if reg.name.find('qPloneSkinLite') >= 0:
        print 'Unregistering %s %s' % (reg.name, str(reg))
        if sm.unregisterAdapter(factory=reg.factory, required=reg.required, provided=reg.provided, name=reg.name):
            print 'Success'
        else:
            print 'Failure'
    
    import transaction
    transaction.commit()
    

    The key is the reg.name.find('qPloneSkinLite') line. If your unwanted adapter is a different one you can view all the registered adapters by running

    sm = app.PORTAL.getSiteManager()
    adapters = sm.registeredAdapters()
    
    for reg in adapters:
        print reg 
    

    Remember to remove the offending product code from your products directory afterwards!

    Worked for me! :)

  • Last modified July 20, 2012, 4:28 p.m.
    Posted July 20, 2012, 4:13 p.m. by admin

    So I have been meaning to do this for a while but have only just managed to get around to it.

    The code by which this very blog is implemented is now available as a Django app. Hooray!

    I implemented my own blog app not liking what was already available for Django. There were some good ones out there, but they did too much when all I required was a simple system that took care of comments, tags and most importantly allowed me to create posts using a rich text editor that supported the uploading of inline images. I also needed something that displayed code blocks with syntax highlighting. With those goals in mind I started implementing my requirements.

    The result: django-richtext-blog!

    I had always intended to release it to the wider community but needed to spend time packaging it up and providing some documentation.

    The very blog you're reading is implemented with this app, so if you like what you see, give it a try!

    The simplest way to get it installed is to run:

    $ pip install django-richtext-blog
    

    Providing your python environment provides pip. Then just follow the instructions to get the app running in Django.

    Currently it only runs under Django 1.3 due to dependencies. In the future I plan to make it Django 1.4 compatible.

    Python Package Index listing:

    http://pypi.python.org/pypi/django-richtext-blog

    GitHub project page:

    https://github.com/timmygee/django-richtext-blog

    Issues and bugs can be reported to the project issues tracker.

    If you have any queries about the app please get in touch with me at my contact page.

  • Posted July 4, 2012, 7:37 p.m. by admin

    After recently performing an upgrade of a fairly old Plone 3 site to Plone 4.1.3 my client noticed that all the icons for the default Plone content types were missing from the "Add New" drop-down menu.

    After some considerable investigation I put it down to 2 things.

    1. The new Plone 4 "sunburst" theme seems to have dropped icon references in portal_types in favour of defining the icon in CSS instead.
    2. Plone 3 portal_types used an "icon" field to specify the icon image that should go with the menu item but Plone 4 uses an icon expression defined in TAL instead.

    This icon expression (or icon_expr as the field is known) is blank after the Plone 3 to 4 migration. This is why there is no icon next to the content type name in the drop down menu.

    I should say at this point that the theme for my migrated site is based on "Plone Classic Theme" (known as "Plone Default" in Plone 3) and this may well be why I have this missing icons problem.

    It's a simple fix really:

    1. Navigate to portal_types in your plone portal.
    2. Click on "Folder" to bring up the properties for the Folder content type.
    3. Add to the icon_expr field the following TAL expression: string:${portal_url}/folder_icon.gif
    4. Repeat for the rest of the default content types using the appropriate TAL expression from the below list

      Folder
      : string:${portal_url}/folder_icon.gif
      Topic
      : string:${portal_url}/topic_icon.gif
      Event
      : string:${portal_url}/event_icon.gif
      File
      : string:${portal_url}/file_icon.gif
      Image
      : string:${portal_url}/image_icon.gif
      News
      Item: string:${portal_url}/newsitem_icon.gif
      Document
      : string:${portal_url}/document_icon.gif
      Link
      : string:${portal_url}/link_icon.gif

    Or because I couldn't be bothered with such a repetitive task a wrote a script that does this for you!

    Just add a new Python Script at the root of your site, add the below code and run it!

    # Import a standard function, and get the HTML request and response objects.
    from Products.PythonScripts.standard import html_quote
    request = container.REQUEST
    response =  request.response
    
    # Return a string identifying this script.
    print "This is the", script.meta_type, '"%s"' % script.getId(),
    if script.title:
        print "(%s)" % html_quote(script.title),
    print "in", container.absolute_url()
    
    if not hasattr(context, 'portal_type') or context.portal_type != 'Plone Site':
        print 'This script must be run in a Plone Site context!'
        return printed
    
    icon_exprs = {
        'Folder': 'string:${portal_url}/folder_icon.gif',
        'Topic': 'string:${portal_url}/topic_icon.gif',
        'Event': 'string:${portal_url}/event_icon.gif',
        'File': 'string:${portal_url}/file_icon.gif',
        'Image': 'string:${portal_url}/image_icon.gif',
        'News Item': 'string:${portal_url}/newsitem_icon.gif',
        'Document': 'string:${portal_url}/document_icon.gif',
        'Link': 'string:${portal_url}/link_icon.gif'
        }
    
    types_tool = context.portal_types
    
    for portal_type, icon_expr in icon_exprs.items():
        if portal_type not in types_tool:
            print 'WARNING: Default plone portal_type %s not in portal_types tool. Not updating icon' % portal_type
            continue
        print 'INFO: Updating icon_expr for %s to %s' % (portal_type, icon_expr)
        types_tool[portal_type].manage_changeProperties(icon_expr=icon_expr)
    
    return printed
    
  • Last modified July 4, 2012, 1:34 p.m.
    Posted July 4, 2012, 1:30 p.m. by admin

    I am using this post to maintain a list of the useful but somewhat obscure commands for the exim MTA. Mostly for my reference but others might find it useful too.

    Display all mail messages in the queue:

    # exim -bp
    

    Unfreeze all messages in the queue. This forces exim to try and send all frozen messages:

    # exim -qff
    

    Clear a single mail message from the queue:

    # exim -Mrm {message-id}
    

    Clear all mail messages from the queue:

    # exim -bp | awk '/^ *[0-9]+[mhd]/{print "exim -Mrm " $3}' | bash
    
  • Last modified June 29, 2012, 12:38 a.m.
    Posted June 29, 2012, 12:27 a.m. by admin

    I honestly had no idea but I think I now know why one channel was always slightly louder than the other channel when playing vinyl on my turntables.

    After watching this video I have the feeling that there must be millions of uncalibrated DJ turntables out there. A sad thought indeed given vinyl is often the audiophile's medium of choice!

    You might have already know that anti-skating stops the needle from jumping out of the groove as easily. Scratch DJs usually crank the setting right up. What you probably didn't know is how to calibrate it correctly for every purpose.

    Check out this excellent video for more.

  • Posted June 29, 2012, 12:02 a.m. by admin

    R18+ Banner

    Well that only took 10 years! Seriously it's taken the Federal Government this long to allow games the same rating tiers as movies and television.

    Great that it's here though. Pity it won't be enacted until at least January 2013. There is speculation that the legislation may get reversed at a state level, which would be a damn shame given how long it's taken the Federal Government to get its act together!

    I'm an adult and I am happy that the government finally acknowledges my right to choose what I can and cannot play.

    Good game did a really good video segment on this Tuesday night and can be viewed here.

    Latest news (and source of the above banner) here.

     

  • Last modified May 24, 2012, 12:57 a.m.
    Posted May 22, 2012, 3:07 p.m. by admin

    I first discovered this issue when trying to set up a ZEO server with multiple filestorages under Plone 4.

    At time of writing the latest version of collective.recipe.filestorage is 0.6 with no sign of getting updated.

    For those not in the know, collective.recipe.filestorage is a very handy utility that allows you to easily configure multiple storages (filestorage, blobstorage) behind a single Zeoserver from your buildout configuration. This is essential to the way I'm currently handling my client's infrastructure in the Amazon cloud.

    Basically the problem is if you configure zeo-address in your plone.recipe.zope2instance section to be zeohostname:8100 but the zeoserver itself is set to bind to 0.0.0.0:8100 (also essential in my client's infrastructure), collective.recipe.filestorage will not detect that as a match and will not complete the required configuration that allow the zope clients to be correctly configured with the extra storage information.

    I have submitted a patch to the code maintainers here but I haven't had any response so I'm not sure how active the project is anymore.

    The patch needs to be applied to __init__.py under collective/recipe/filestorage in the egg.

    You can get the patch that needs to be applied to that file from the above link or here for convenience.

    The contents of the patch for posterity:

    41,42c41,50
    <                     if zeo_address is None or zeo_address == part.get('zeo-address', 8100):
    <                         self.zope_parts.append(part_name)
    ---
    >                     try:
    >                         zeo_host, zeo_port = zeo_address.split(':')
    >                     except ValueError, AttributeError:
    >                         if zeo_address is None or zeo_address == part.get('zeo-address', 8100):
    >                             self.zope_parts.append(part_name)
    >                     else:
    >                         zope_address = part.get('zeo-address', '8100')
    >                         zope_tokens = zope_address.split(':')
    >                         if zeo_port == zope_tokens[-1]:
    >                             self.zope_parts.append(part_name)
    

    It just makes the process a little bit smarter. It still makes the same assumption as the original code, that the port number of the zeo server uniquely identifies it. What it does differently is allows for the format where the IP address is specified, thus allowing the correct configuration of the Zope clients with regards to the multiple storages.

  • Last modified May 24, 2012, 1:14 a.m.
    Posted May 15, 2012, 11:45 p.m. by admin

    Getting emacs right when it comes to making it Django dev friendly can be fiddly. Here's how I did it.

    I did this on Debian 7 "wheezy", so your mileage may vary. I would imagine you will have similar results on a recent version of Ubuntu.

    Step 1 - Install and configure django html syntax highlighting

    First, get the files in place

    cd ~/.emacs.d
    wget http://ourcomments.org/Emacs/DL/elisp/nxhtml/zip/nxhtml-2.08-100425.zip
    unzip nxhtml-2.08-100425.zip
    

    Next, edit your .emacs file. I've used vim as the editor here but feel free to use what you're most comfortable with. Even emacs will do!

    cd ~/
    vim .emacs
    

    Add the following lines of code to the end of the file.

    ;; ---------------------------------------------------------------------------
    ;; For django html
    (autoload 'django-html-mumamo-mode "~/.emacs.d/nxhtml/autostart.el")
    (setq auto-mode-alist
    (append '(("\\.html?$" . django-html-mumamo-mode)) auto-mode-alist))
    (setq mumamo-background-colors nil)
    (add-to-list 'auto-mode-alist '("\\.html$" . django-html-mumamo-mode))
    

    Try running emacs. If you get the following error:

    Warning: 'font-lock-beginning-of-syntax-function' is an obsolete variable (as
    of Emacs 23.3); use 'syntax-begin-function' instead.
    

    Run this from the command line:

    replace font-lock-beginning-of-syntax-function syntax-begin-function -- .emacs.d/nxhtml/util/mumamo.el
    

    Step 2 - Configure a colour scheme

    I generally work in a terminal with white text on a black background so my theme choice was color-theme-hober. After the colour scheme is installed there is a ton to chose from. From within emacs META-x, then type "color-theme-". Tap the tab key a couple of times to see all the options.

    If you're using Ubuntu/Debian the colour theme should be an installable package via apt. I took most of these steps from this resource here.

    If you can't use apt, you can download the colour themes from here. Otherwise run:

    sudo apt-get install emacs-goodies-el
    

    From a terminal (once again you can use your editor of choice here).

    vim ~/.emacs
    

    Add the lines:

    ;; ---------------------------------------------------------------------------
    ;; Color-theme
    (add-to-list 'load-path "/usr/share/emacs/site-lisp/emacs-goodies-el/color-theme.el")
    (require 'color-theme)
    (eval-after-load "color-theme"
    '(progn
    (color-theme-initialize)
    (color-theme-hober)))
    

    Replace "color-theme-hober" with another option if you prefer a different colour scheme.

    Step 3 - Add an 80 character column marker

    This step is optional but it's a nice way to get emacs to tell you that you're going over the standard 80 character terminal width.

    Taken from instructions here.

    Install the colomn-marker feature by running the following from a terminal:

    cd ~/.emacs.d
    wget http://www.emacswiki.org/emacs/download/column-marker.el
    

    Once again, edit your .emacs file and add the following lines to the bottom:

    ;; ---------------------------------------------------------------------------
    ;; Column Marker
    (require 'column-marker)
    (add-hook 'python-mode-hook (lambda () (interactive) (column-marker-1 79)))
    

    Note that the column-marker-1 value is 79 not 80. This is because emacs will wrap one character early if a line reaches 80 characters.

    Run emacs again. If you get loading issues add the following to the top of your .emacs file:

    (add-to-list 'load-path "~/.emacs.d/") 
    

    Step 4 - Additional configurations

    Below are some more configurations you can add to emacs that I find rather handy.

    Add any of these code snippets to the end of your .emacs file

    For adding the shortcut key combination META-g to bring up the goto-line feature:

    ;; Set goto line
    (global-set-key "\M-g" 'goto-line)
    

    Ensure files when saved end with a newline character:

    ;; Always end a file with a newline
    (setq require-final-newline t)
    

    Switch off the menu bar I find pretty useless and free up another line for text!

    ;; Turn off menu bar
    (menu-bar-mode -1)
    

    For posterity - here's my whole .emacs file with all configs in one:

    (add-to-list 'load-path "~/.emacs.d/")
    
    ;; ---------------------------------------------------------------------------
    ;; Column Marker
    (require 'column-marker)
    (add-hook 'python-mode-hook (lambda () (interactive) (column-marker-1 79)))
    
    ;; ---------------------------------------------------------------------------
    ;; For django html
    (autoload 'django-html-mumamo-mode "~/.emacs.d/nxhtml/autostart.el")
    (setq auto-mode-alist
    (append '(("\\.html?$" . django-html-mumamo-mode)) auto-mode-alist))
    (setq mumamo-background-colors nil)
    (add-to-list 'auto-mode-alist '("\\.html$" . django-html-mumamo-mode))
    
    ;; ---------------------------------------------------------------------------
    ;; Color-theme
    (add-to-list 'load-path "/usr/share/emacs/site-lisp/emacs-goodies-el/color-theme.el")
    (require 'color-theme)
    (eval-after-load "color-theme"
    '(progn
    (color-theme-initialize)
    (color-theme-hober)))
    
    ;; Set goto line
    (global-set-key "\M-g" 'goto-line)
    
    ;; Always end a file with a newline
    (setq require-final-newline t)
    
    ;; Turn off menu bar
    (menu-bar-mode -1)
    
  • Last modified May 15, 2012, 11:14 p.m.
    Posted May 15, 2012, 11:12 p.m. by admin

    But it just might help someone out...

    I've relied on the kindness of strangers in order to solve the daily problems I face as a developer for too long. I figure it's time to give back a little.

    If it's something I couldn't find a fix for and then subsequently solved the problem myself, you'll find it here. I also plan to document anything I release as open source here, including the code that implemented this blog once I get to packaging it up!