2011/07/19

Bio by Pictures

第一台電腦是 PC XT 8088 的時代,當時是買 Acer 但找不到照片,只好用這張類似的畫面。全機黑色的 Acer XT 比這漂亮太多了。

中學時代的電腦,主要是遊戲機的功能,學 BASIC 的目的,也是想寫出自己的遊戲。

自己是搖滾迷,id nickname 是取自英國樂團吉他手的名字。

第一個網站,內容是介紹搖滾樂。

架站總是要學 Unix 知識,後來發現歷史故事也充滿趣味。

現在是 Python 愛好者一枚。

2011/07/03

New User Interface Preview

Plone 操作介面的發展規劃,經過 Plone UI Sprint 的努力工作後,終於有了 plone.app.cmsui 測試版實作,搭配 Plone 4.1 環境,讓我們可以體驗新介面的預覽版。
https://lh3.googleusercontent.com/-jnpfZ9f-6KI/Tg_WHllBbTI/AAAAAAAAC1k/avTn8KV-JkQ/s640/cmsui-frontpage.png
另一個改版重點,是導入新的 page layout 管理機制,底層是一個稱為 Block 的引擎,它將網頁分成結構式和動態的顯示元件,經過組合再呈現。短期內,Plone 則推出 plone.app.page 讓 Folderish Page 取代 Folder,許多測試正在演進中。

2011/06/30

Change Archetypes CreationDate

建立 Plone 內容時,系統會自動指定建立時間,想要竄改這個時間,可以用 bin/plonectl debug 存取 Data.fs,以 app.mysite.news['my-news'] 為例,使用 created() 這個 accessor 可以查詢建立時間,使用 setCreationDate() 這個 mutator 可以指定建立時間,完成之後要記得 transaction.commit()。再進 ZMI 的 portal_catalog 重新執行 created 的索引動作。
在 Products/Archetypes/ExtensibleMetadata.py 可以看到程式碼細節。

2011/06/28

Plone BlobStorage and Image

下列是使用 Plone 4.0.7 實測 Blob 功能的記錄。

新增一個 Image,附的圖檔約 1.4MB,看到 var/blobstorage 裡出現一個 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x5b/0x038f4c3af3551d22.blob 檔案,大小 1486990,驗證圖檔放進 blobstorage 裡,值得注意的是,同時伴隨產生一個 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x66/0x038f4c3af6acde66.blob 檔案,大小 40615。

在 Plone 裡把上述圖檔刪除,原本 blobstorage 對應的檔案仍然存在,並未馬上被刪除,直到執行 pack 之後,blobstorage 裡面剩下 0x00/0x00/0x00/0x00/0x00/0x00/0x20 目錄,底下的檔案都被刪除。

接著,即使重複上述的圖檔新增動作,上傳同樣圖檔,blobstorage 會產生新的對應檔名,例如 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x6e/0x038f4c4d455447cc.blob (size 1486990) 和 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x75/0x038f4c4d482af9ee.blob (size 40615)。

新增一個 File,附的檔案指定上述的圖檔,blobstorage 則會產生 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x7d/0x038f4c7f2e73e400.blob (size 1486990),但是沒有產生大小為 40615 的伴隨檔案。

如果編輯舊的 File,上傳新的檔案,則會對應產生 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x88/0x038f4cd0ba71df00.blob (size 11080872) 新檔案,原本的 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x7d/0x038f4c7f2e73e400.blob (size 1486990) 仍然存在,直到執行 pack 之後,才會只剩 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0x88/0x038f4cd0ba71df00.blob (size 11080872)。

另外,新增 News Item 時,預設有兩種方式來上傳圖檔。一種是從 Image 欄位上傳圖檔,這種方式並不會在 blobstorage 裡產生對應的檔案,相同目錄裡也看不到對應的 ATImage 檔案,暫不清楚跟 show_content_type 是否相關。另一種方式是從 RichWidget 欄位上傳圖檔,這種方式會在 News Item 相同的目錄裡,建立對應的 ATImage 檔案,同時也在 blobstorage 裡產生 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0xd1/0x038f4cde1e238bee.blob (size 1486990) 和 0x00/0x00/0x00/0x00/0x00/0x00/0x20/0xd6/0x038f4cde20a1d711.blob (size 6285) 的對應檔案,效果等同先建立 ATImage 再於 RichWidget 裡指定連結。

額外一提的是,如果 RichWidget 欄位上傳的圖檔,目錄已存在相同檔名的檔案,則會自動更名為 copy_of_SomeImage.jpg 之類的識別碼。

使用 blobstorage 後,即使所有的 Image File 都清掉,在檔案系統裡還是會留下之前建立過的目錄:
var/blobstorage/
├── 0x00
│   └── 0x00
│   └── 0x00
│   └── 0x00
│   └── 0x00
│   └── 0x00
│   ├── 0x20
│   └── 0x21
└── tmp

2011/06/21

Add Custom Field to Criteria in ATTopic

以 Plone site 的 events/aggregator 為例,點選 Criteria 頁籤,可以編輯選集的條件,這個編輯頁面使用 Products/ATContentTypes/skins/ATContentTypes/criterion_edit_form.cpt 程式碼,摘要如下:

<div class="field" style="float:left">

<label for="field">Field name</label>

<div class="formHelp"
id="fieldHelpSort">
List Available Fields
</div>

<select name="field"
id="sortfield"
tal:define="fields context/listSortFields">

<option value="no_sort"
tal:attributes="selected python:not context.hasSortCriterion();"
>No sort order</option>

<tal:block tal:repeat="field fields">
<option value=""
tal:define="explanation python:field[2]"
tal:attributes="value python:field[0];
selected python:context.hasSortCriterion()
and context.getSortCriterion().field==field[0];
title explanation"
tal:content="python:field[1]"
i18n:attributes="title"
i18n:translate="">Field</option>
</tal:block>
</select>

</div>
其中的 listSortFields 定義在 content/topic.py 裡。
想在條件裡新增自製欄位的話,最簡單的方式,是到 Site Setup 的 Collections 裡設定,例如點擊 All fields 後,再勾選 Contributors 選項,讓它成為啟用的項目。

https://lh4.googleusercontent.com/-sjn9-Kzs9V8/TgAzjwrAi_I/AAAAAAAAC0I/s5uYBx36cgk/s800/collection-indexes.png

2011/06/01

Migration In Action

看過昇級的背景資訊後,可以真的動手了。

Plone 3.3.5 昇級到 4.0.x,算是相對容易的情境,原則上,把 Plone 3.3.5 選用或自製的模組版本,盡量先更新到合適的號碼,這樣就可以準備一份夠好的 Data.fs。再次提醒,實際昇級前,一定要把 Data.fs 備份好,完成昇級步驟後,還要進行許多測試工作,途中遇到錯誤的話,還是可能要用到 Data.fs 備份檔。

Plone 3.3.5 和 4.0.x 都有 buildout 工具,利用 buildout 就可以把許多昇級工作搞定,昇級 buildout.cfg 最簡單的方式,是先用 Unified Installer 安裝系統,再把 egg 和其他設定值搬到 buildout.cfg 裡。

依據上述的原則,下列是實戰過程的記錄。

舉例來說,原本 Plone 3.3.5 搭配 Ploneboard 2.0,先昇到 Ploneboard 2.2 之後,就可以同時在 Plone3 和 Plone4 使用。不過,Ploneboard 搭配的 python-dateutil,要使用 1.5 版本,處理方式是在 [versions] 設定區段,指定為 python-dateutil = 1.5,如果安裝 python-dateutil 2.0 的話,會造成 Ploneboard 無法執行,處理方法是刪掉 python-dateutil 2.0 再裝 1.5 版本。

webcouturier.dropdownmenu 模組也有類似的情況,它的 2.0 版本是搭配 Plone 3.x,到 2.1 版本就同時支援 Plone 3 和 4。另外,我是昇級 Plone4 後才發現 webcouturier 有 2.1 版,事後再昇級 webcouturier 並沒問題。

設定 Plone 4.0.5 的 buildout.cfg 時,記得把 Products.PloneHotfix 加上去,執行 bin/buildout 之後,把舊系統的 Data.fs 放到 var/filestorage 目錄,執行 bin/plonectl debug 來啟動新系統,總之,要等完成昇級測試後,再改用 bin/plonectl start。

進 ZMI 的昇級畫面後,先勾選 dry run 執行模擬,接著有一系列的昇級動作,其中的 plone.app.upgrade 在 v40/betas.py 檔案裡,定義了 convertToBlobs() 函式,會把 File 和 Image 轉存為 Blob 檔案,這個過程會把舊檔刪除,再建立新檔,如果舊站已存在許多 File 和 Image 的話,這個步驟會花很長的時間。

手邊一個 9.6G Data.fs 建立 6.5G blobstorage,最後 Data.fs 剩下 278.9M,因此,執行昇級前最好留有 Data.fs 一倍以上的硬碟空間。

2011/05/22

The Python Paradox

This is a zh-tw translation of The Python Paradox by Paul Graham.

在某次演講中,我的話語惹毛不少人,那段話是這樣說的 -「使用 Python 的專案,會比 Java 的專案,容易吸引到更聰明的程式人員。」

我可沒說 Java 程式員是笨的,那句話的焦點在於 Python 程式員是聰明的。學習一個新的程式語言,需要花費不少工夫,因此,人們不會為了混口飯吃,而去學 Python,那些學 Python 的程式員,是基於對編程的熱愛,而且他們對已知的語言都感到不滿意。

這類的程式員,應該是公司想要雇用的。由於找不到好的形容詞,我姑且稱這種現象是 Python 的弔詭 - 如果公司的軟體專案使用密教式的語言來開發,他們會雇用到較好的程式員,因為這樣的條件會吸引那些願意學這類語言的好手。對程式人員而言,下列的說法,更是無庸置疑:如果你想要找到好工作,該學的語言,必然不是那些只能混口飯吃的語言。

迄今,只有很少的公司夠聰明,能明白這樣的道理,不過,還有另一種演化趨勢,來自於那些最受程式員喜愛的公司,例如 Google,當他們要找 Java 工程師時,也會要求同時具備 Python 經驗。

我有個朋友,熟知所有廣被使用的語言,他手邊的專案,多數就用 Python 開發,而選用 Python 的最大原因,是程式碼看起來舒服。比較程式語言的選用條件時,這樣的理由聽起來可能好笑,但搭配下列的情境,這句話就不像鬧著玩了:動手編程時,你會花很多時間在讀程式碼,而不是寫程式碼。編修程式碼的過程,就像雕塑師在作品上捏塑泥巴的過程,如果語言讓程式碼變醜,嚴謹的程式員看了可會抓狂,就像糊成一團的泥巴,會讓雕塑師無法忍受一樣。

提到醜的程式碼,人們很容易想到 Perl,不過,Perl 表面上的醜,或是生硬語法所帶來的醜,並不是我想講的,錯誤概念所造成的醜,才是真的讓人無法接受的事。有時候 Perl 程式碼看起來像卡通人物幹譙時的一串符號,但有些情況下,Perl 在概念上比 Python 來得優異。

話說回來,這兩個語言仍然各自演化中,和 Ruby (Icon, Joy, J, Lisp, Smalltalk) 一樣,投身它們的程式員,都是熱愛編程的族群,而且是更有機會搞好編程的一群。