Some plugins need to store data between Pyblosxom requests. Take for example my viewcounts plugin which keeps track of how many times a given entry has been viewed. This data is stored as a pickled dict of entryid -> view count in a viewcounts.dat file in my datadir.
My viewcounts plugin does two things. First, it displays the current number of times a given entry has been viewed. Second, it updates this number. This creates a class read/write serialization problem where two or more processes could be trying to read and modify the data at the same time. This is solved by serializing the processes so that only one process is reading and modifying the data at a time.
There are a couple of ways you can store this data. First, you could store it in a database--which handles serialization and all that sort of stuff for you in transactions.
The other way is to use the tools module's lock/unlock functions (from the Python Cookbook portalocker code). For example:
from Pyblosxom import tools
import pickle
def cb_start(args):
request = args["request"]
data = request.getData()
config = request.getConfiguration()
datadir = config["datadir"]
f = file(datadir + "/mydatafile.dat", "r+")
tools.lock(f, tools.LOCK_EX)
data["myplugin_datafile"] = f
data["myplugin_data"] = pickle.load(f)
def cb_story(args):
# We can use the data file anywhere--I'll just use it
# here to show the example code.
request = args["request"]
data = request.getData()
# get the data we saved in cb_start....
d = data["myplugin_data"]
# do our data modification here...
...
def cb_end(args):
request = args["request"]
data = request.getData()
f = data[""myplugin_datafile"]
d = data["myplugin_data"]
# set the pointer back to the beginning of the file
f.seek(0, 0)
# dump the modified data back to the file
pickle.dump(d, f, 1)
# close the file
f.close()
tools.unlock(f)
That's pretty much it.
changelog
You've just finished the most fantastic plugin ever and you want to give it to everyone! Woah Nelly--before you distribute it, think of these things!!!
First off, you should make sure you have some kind of license statement in the plugin. What can users do with the plugin? Can they modify and redistribute it? Do they have to pay for usage? Blah blah blah (feel free to steal my license statement).
Second, you should have a copyright notice in the plugin header so people know who owns it.
Third, in order for people to know which version they have and thereby recognize when there is a new version and such, you should have the following items:
Then you should include instructions on how to set up the plugin (any config.py parameters that need to be set, any flavour files that need to be created, other data files that need to exist, ...), how to use the plugin (what variables it might expose to templates, urls that it does things with, ...), and whatever other documentation the user would want to know.
Doing all of this will help the user know what they've downloaded, how to use it, what it does do, what it doesn't do, how to figure out when a new version is out, and what rights they have.
For examples, look at the headers of all my plugins in my plugin index.
changelog
If you're writing plugins and you need a place to do some debug printing, the easiest thing to do is to toss a "$debugprint" variable in your foot.html file (or whatever flavour file you want to toss it in). Then every time you want to print a debug statement, do something like this:
request = args["request"]
data = request.getData()
debugprint = data.get("debugprint", "")
data["debugprint"] = debugprint + "\nyour print statement here"
The neat thing about this is that you can leave the $debugprint in your flavour template file when you're done. If the variable is not defined or it doesn't have any data, it gets removed.
changelog
Some plugins can do all their functionality in one callback and don't have any need to store state. These are your simple plugins that do things like count how many words there are in an entry and then store that number in the entry object's properties. More complex plugins do some stuff in one callback, then need to store their state, and do some other things in another callback.
In PyBlosxom 0.8 and prior, you could do this by storing the state in global variables on the plugin module like this:
state = {}
def cb_date_head(args):
global state
if state.has_key(...):
...
def cb_filelist(args):
global state
...
state["blah"] = "blahblah"
This is "ok" for previous versions of PyBlosxom. In future versions (post 0.8), this is not ok and the official way to maintain state is to store state information on the Request object in the data dict using a unique key:
STATE_KEY = "myplugin_state"
def cb_date_head(args):
request = args["request"]
data = request.getData()
if data.has_key(STATE_KEY) and data[STATE_KEY]["blah"] == "blahblah":
...
def cb_filelist(args):
request = args["request"]
data = request.getData()
data[STATE_KEY] = {}
data[STATE_KEY]["blah"] = "blahblah"
changelog
All contents Copyright 1996 to 2008 Will Guaraldi.
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.