Scripter FAQ

Scripter FAQ

Author: Craig Ringer

How do I use non-ASCII text in the scripter?

First, make sure to ensure that your script has a correct coding line. Your script should start with something like:

    #!/usr/bin/env Python
    # -*- coding: latin-1 -*-
or
    #!/usr/bin/env Python
    # -*- coding: utf-8 -*-
or
    #!/usr/bin/env Python
    # -*- coding: ascii -*-

Those lines must be the first two lines of your script. The coding must match the actual encoding of the file.

To find out what the text encoding is in vim, type :set fileencoding? How to find out the text encoding will vary for other editors, it may match your locale. The file command is not a reliable way to determine the text encoding of a file.

You can convert files between encodings with the 'iconv' utility, but you will rarely need to given that Python can handle almost any text encoding if told what it is in the coding line.

A few scripter functions require strict ASCII text, and cannot accept unicode or latin-1 text. If you call one of those with non-ASCII text, you'll get an error like: UnicodeDecodeError: 'ASCII' codec can't decode byte 0xc3 in position 1: ordinal not in range(128) which is admittedly less than helpful.

There currently seems to be a bug with the u'' modifier for string literals in the script console. This problem has also been identified in the Python interactive interpreter on the command line. It does not affect script files. Until this is solved, use the unicode("mystring") constructor or just use plain strings (which can contain unicode text) from the script console.

What's a good structure to use for my scripts?

Start with 'boilerplate.py' in the samples directory. That script disables redraws (for speed) and has code to make sure they get turned back on, does some checking and reports a useful error if run outside of scribus, etc.

Why Python?

It's well suited to application embedding, but still full-featured and powerful. It's also accessible to new users and well documented. Additionally, it has solid unicode text support.

Python makes a good glue language to connect different programs and components together. For example, you may wish you make it possible to use your in-house story database with Scribus - in which case the Python interface is probably the simplest and quickest way to get you there.

It's also somewhat easier to write tidy Python code that other people can read and understand. If somebody else's script doesn't quite do what you need, with Python you have more of a chance of modifying it so it does.

There are issues with embedding Python in applications, so from the perspective of pure automation scripting a language like Qt Script for Applications or lua might be better suited. If you want to get beyond simple automation, Python seems to be the way to go.

I want to provide a more complex GUI than is provided by the dialogs built into the scripting interface. How can I do that?

For most scripting tasks, building a simple GUI in Tkinter is your best choices at present. If you're looking to extend the user interface or provide palettes the user can work with while they continue to work in Scribus, you'll need to look into writing an 'extension script' with PyQt.

In most cases it's recommended to just choose Tkinter. It's the only GUI toolkit that works reliably in normal Scribus scripts due to the way they're executed in sub-interpreters. It's also almost universally packaged in Linux distros, though not all install it by default, and it's highly portable. Users may not particularly love the appearance of Tkinter, but it works well.

If you're looking to write more advanced GUIs, the best choice is currently PyQt. You can write your own custom dialogs and palettes using PyQt, giving you the ability to extend the Scribus interface to a limited extent. PyQt will not work reliably from a normal script, but works fine from scripts that are run using the "Load Extension Script..." menu item. Please see the advanced section of the scripter manual for more details on this.

Issues with event loop integration and initialization in sub-interpreters mean that PyGtk and wxPython are not currently recommended and probably won't work properly. Given that Tkinter works well for normal scripts, and PyQt for more advanced tasks, this isn't seen as a major problem.

Should I use 'from scribus import *' or 'import scribus'?

In general, 'import scribus' is preferred. 'from ... import' can get confusing in import loops, when reloading modules, when importing packages, and in some other circumstances. More info http://effbot.org/zone/import-confusion.htm.

While 'import scribus' results in slightly more verbose code, it's generally worth it in improved code readability and explictness.

What about general programming style?

In general, we defer to the Python gurus. Have a look at http://www.Python.org/peps/pep-0008.html for a rather in-depth look at the subject.

An exception is made for source code encodings, where either ASCII with escapes, latin-1, or utf-8 are recommended. Almost any encoding you choose should work fine, though.

Please note that none of this is set in stone - you can code however you like. These recommendations are made for a reason though, and are a good idea to follow especially if you plan to share your code with others.

Are there any quirks specific to the Scribus Python interface that I should know about?

Yes, there are a few differences you should be aware of:

Can I use the rest of the Python standard library or add-in modules?

Yes, and yes. Scribus imposes no restrictions on access to the rest of Python (except for the technical limitations explained above), and that's one of the things that makes the scripter so powerful. It is possible that some Python functions such as threading may be affected by the way the interpreter has been embedded, but most should be usable as normal.

I'd like to extend Scribus using Python, not just automate things with it...

Currently, that's not really possible. There is work on making it possible to extend Scribus with Python to some extent, especially the GUI. It's now possible to use PyQt to write your own palettes, but you won't be able to use custom Scribus widgets or get into the innards of the application. The Scribus core is unfortunately not well suited to extension from Python. More advanced or tightly integrated extensions are probably better written as C++ plug-ins.

What about security? Can I trust scripts not to destroy my data or compromise my computer?

No. Do not run a script if it is not from a trusted source, and preferably not unless you have read it. The downside of the power of the Python scripting interface is that it imposes almost no security restrictions. Anything you can do from the shell without a password, a script can do too.

If Python ever gets support for a restricted execution environment like versions < 2.2 had, support for it may be added, but currently there are essentially no restrictions. It would be interesting to investigate a simple automation-only macro language for embedding in Scribus, but currently there aren't the resources to do this.

So ... can I embed scripts in documents or templates?

No, see above. We can't provide a restricted execution environment, so it's not safe to let scripts travel with documents. Otherwise a malicious script could use a document as a vector to infect other systems. Remember Word macro viruses? Yeah. We do too.

What about a startup script or event-triggered scripts?

Startup scripts are supported, and scripts that run when certain events happen may be supported in future. If a script is in a position to "infect" a startup script or your application, it's also able to modify your .bashrc or your X startup script. In other words, if you choose to run untrusted code on your machine, it's too late - having it insert its self into a Scribus startup script would be the least of your problems. This is not unique to Scribus, and is true of bash scripts, normal programs, and most plug-ins as well. Remember, do not run scripts that are not from trusted sources, scripts are programs like any other you might run on your computer..

It's as safe for Scribus to load a script on startup as it is for the shell (e.g. bash), or your graphical login system. Scribus cannot protect you if you choose to run untrusted programs on your system. What it can prevent is providing any vector for untrusted code to spread. That is why Scribus supports startup scripts (though they are not run by default) and why scripts will not be permitted to be embedded in or run from documents.

Do not run a program, script, or plug-in, of any sort, from any source, unless you have verified that the program is not malicious. This is an important rule of basic computer security and applies to any program and operating system.

What about C++ plugins for Scribus? Are they secure?

Not at all. A Scribus C++ plug-in can do almost anything any other program on your computer can do, so do not download and run one you do not absolutely trust the author of. This is true of plug-ins for most programs, as it is very difficult to restrict what a plug-in written in C/C++ can do.

I can't find a way to do something from Python, but the main Scribus application supports it. What do I do?

The scripting interface currently requires each function to be written by hand - no automatic code generation / wrapping mechanism is used. This is partly because there isn't currently any tidy and stable underlying public API to wrap.

In general, if a function is missing it is because nobody has found the time or need to write it yet. Sometimes the function is more complicated than it seems, and may be quite a lot of work to wrap. Sometimes it's five minutes work. Ask politely on IRC or the mailing list, and if someone has the time and inclination they may write one for you.

I asked on the mailing list or IRC but nobody offered to write this function I need for the scripter. What can I do?

You have a few options:

Where can I get hints about Unicode ?

http://www.cl.cam.ac.uk/~mgk25/unicode.html