Exaile豆瓣电台插件0.0.11发布

很高兴时隔半年后我继续发布了Exaile豆瓣电台插件的更新,从第一个版本发布到现在已经有一年半的时间,这期间豆瓣电台插件已经陆续出现在Rhythmbox、Banshee等播放器上。作为第一个视图把豆瓣电台移植到本地的尝试,我感到甚是欣慰:)

这次的更新修正了长久依赖困绕用户登录问题,现在我们有一个专门的界面来输入验证码。这个功能要感谢DigitalPig用户在github的报告(鞭策作用),此外,我参考了豆瓣电台banshee插件的实现,节省了研究含验证码登录的时间,感谢。总而言之,没有用户的推动,这个项目也不会坚持这么久。

除此之外,插件还有一些支持了新的豆瓣说的推荐,优化了播放列表载入的策略。

另外值得highlight的是,对应的gnome-shell扩展发布了0.0.2版本,唯一的更新是专辑封面现在会显示在gnome-shell的菜单中。

你可以从github获得最新的插件和gnome-shell扩展:

有任何问题都可以在github或这里留言。

My response to Spark: Visualize your mercurial commit history from commandline

标题长了些。还是用母语吧。

昨天HackerNews上一个小脚本轰动了,所谓山不在高程序不在小。为了响应这个小脚本,我写了一个更加简单的Mercurial(hg)扩展,帮助你输出hg仓库的提交历史。这个feature和github的直方图有点像,在我看来github的直方图是他们最重要的feature之一,它鞭策着你不断地commit。

hg summary

安装:将这个脚本放在任意一处,在你的hgrc中添加:

[extensions]
summary = /path/to/your/script

由于很简单,就不按照mercurial的规范发布了。

Convert a Python function to Java anonymous class

When calling Java with Jython, anonymous inner class might be an issue because there is no such equivalent in Python.

In GUI programming, jython made additional effort on AWT event processing. You can pass a python function as some types of event listener.

def change_text(event):
    print 'Clicked!'

button = JButton('Click Me!', actionPerformed=change_text)
frame.add(button)

Described in the Definitive Guide of Jython:

This works because Jython is able to automatically recognize events in Java code if they have corresponding addEvent()* and *removeEvent() methods. Jython takes the name of the event and makes it accessible using the nice Python syntax as long as the event methods are public.

However, it does not work with Runnable, Callable and many other interfaces designed for anonymous usage.

To solve the incompatibility, I created a small decorator that converts Python function to a Java object.

Thanks to python’s dynamic magic, we can create class in runtime and assign modified method to a particular instance. The conversion is performed once the function loaded. Also, you can pass something as arguments to constructor.

With anonymous_class decorator, the example above can be written as:

from javax.swing import JButton, JFrame
from java.awt.event import ActionListener

frame = JFrame('Hello, Jython!',
            defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
            size = (300, 300)
        )

@anonymous_class(ActionListener, "actionPerformed")
def change_text(dummy, event):
    print 'Clicked!'

button = JButton('Click Me!', actionPerformed=change_text)
frame.add(button)
frame.visible = True

Don't repeat yourself: distribute jython package with jip.dist

As a new feature in jip 0.4, we can use some helpers from jip.dist to simplify package distribution. With jip.dist, you can define Java dependencies for your jython package. In an environment with jip, dependencies will be automatically installed when user uses pip to get you package.

We have two different approaches allow you to choose.

Approach 1, Define dependencies in POM

This is the standard maven way. To describe your jython package and its dependencies, create a pom.xml in your project. The directory hierarchy looks like:

├── app
│   ├── module1
│   │   ├── __init__.py
│   ├── core.py
│   ├── __init__.py
├── LICENSE
├── MANIFEST.in
├── pom.xml
├── README
└── setup.py

In pom.xml, just add dependencies as you do with Maven.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <br="" />  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;

    ...

    <dependencies>
        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>slf4j-api</artifactid>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>slf4j-log4j12</artifactid>
            <version>1.6.1</version>
        </dependency>

        ...

    </dependencies>

    <repositories>
        <repository>
            <id>sonatype-oss-sonatype</id>
            <url>http://oss.sonatype.org/content/repositories/snapshots/</url>
        </repository>
    </repositories>
</project>

You can also define repositories in pom.xml if you use custom repository. (for example, jboss, java.net)

Remember to add pom.xml in your MANIFEST.in, to ensure the file will be packaged into source package:

include pom.xml

Approach 2, Define dependencies with Python

You may be tired with endless XML configuration. jip allows you to define dependencies with python, just like gradle with groovy.

In your setup.py, add something like:

requires_java = {
    'dependencies':[
        ## (groupdId, artifactId, version)
        ('org.slf4j', 'slf4j-api', '1.6.1'),
        ('org.slf4j', 'slf4j-log4j12', '1.6.1'),
        ('info.sunng.soldat', 'soldat', '1.0-SNAPSHOT'),
        ('org.apache.mina', 'mina-core', '2.0.2')
    ],
    'repositories':[
        ('sonatype-oss-snapshot', 'http://oss.sonatype.org/content/repositories/snapshots/')
    ]
}

Then pass it to setup(). The keyword argument require_java is jip specific.

setup(
    ...
    requires_java=requires_java,
    ...)

Use jip’s setup wrapper

To use jip’s power, the only difference is to use setup() from jip.dist instead of setuptools or distutils.

from jip.dist import setup

Then publish your jython package to Python Cheese Shop:
$ jython setup.py sdist upload

Internally, jip uses setuptools. So you can still do jython setup.py develop .

And jip 0.4 is available under MIT License. You are free to use jip.dist in your code.

For your user

You should write a guide forcing users to use your jython application within virtualenv. And install jip as a prerequisite:
$ pip install jip

Then simply install your package with pip:
$ pip install <your-package-name>

No additional step required!

So please just release your jython package with jip !

For more information:

jip 0.2 released

As you may know, jip is a dependency management tool for Jython/Java development. It resolves and downloads Java packages from maven-compatible repositories. jip also follows some best practices, encouraging you to use a portable and standalone environment (virtualenv) for your Jython development.

It has been four months since the initial release. In version 0.2, I made following changes for you:

  • Improved console output format
  • Correct scope dependency management inheritance
  • Snapshot management, alpha
  • Environment independent configuration
  • Bug fixes

You can find the typical usage doc on github:
https://github.com/sunng87/jip

jip-0.2 has been published to pypi so you can install or upgrade it with:
easy_install -U jip

Please do remember to use it inside virtualenv!