Wednesday, October 15, 2008

Prepping for NaNoWriMo

I just created an account at National Novel Writing Month. I first heard about it last year at Thanksgiving. Since that was smack dab at the end of the month, I couldn't very well enter into it, could I?

So, I'm prepping for it now, by doing some preliminary brainstorming for ideas. I have a few that I like. Now I just need to trim it down to the one idea I will work on for the month.

I'll be updating my author page once November starts. I hope to be able to keep the pace.

Anyone else doing NaNoWriMo this year?

Tuesday, October 14, 2008

Chapter 1, The Path Into Darkness


Path Into Darkness e-book


Spiders skittered around the periphery of his vision. Everything was shrouded in deep shadow; all he could see and hear were the spiders. There were hundreds of them, maybe thousands--crawling over him, on his face, through his hair. He felt the prickling of their steps as they weaved their way over his body.

Something loomed into his vision; a large bloated shape, a glistening black that allowed him to see his own reflection. Small spiders moved over his body, leaving wisps of white silk webbing all about him.

A bright light shone--its sudden appearance startled him--which only served to draw further attention to huge spider hovering over him. It spun webbing, entangling his body within the strands. He struggled against the webs, first tossing his body to the left. Then he threw himself to his right, but the webs were already over his legs and pinned his arms to his sides.

In a panic, Mark craned his head side to side, vainly struggling for a glimpse of his surroundings. It looked like a hospital ward; beds lined the wall he was against as well as the wall opposite him. Other large spiders could be seen, hanging on thick strands of web over the other beds or encasing other forms–-patients he supposed, it was a hospital after all. The chattering sound of mandibles and the clicking of the spiders filled his ears.

Before each bed, a person stood; each was watching the process, some made notes on clipboards. They were all dressed as doctors, but what sort of doctor would stand by idly and watch what was happening?

He struggled to see past the bloated form in front of him, to see if someone stood at the foot of his bed. Straining to see, he was able to see his ″doctor″; the man made no notes and held no clipboard. He was simply watching, occasionally shaking his head and making a sort of clucking sound with his teeth. For some reason--Mark couldn't be sure why--but the man's presence was more upsetting than the spiders.

He looked to be of median age, with short, brown hair and a short, gray-streaked beard and a pair of small eyeglasses. They made brief eye contact, and the other man smiled wryly, saying, "Excita sursum, pro est quoque tardus!"

Once he spoke, the large spider over him stopped and quickly began to move away. The man spoke again, making vigorous hand gestures, "Hora est tardus, quod vos opus efficia. Nunc vigila!"

*


Mark sat bolt upright in his bed, beads of sweat ran down his face,clinging to his body. Through vision still fuzzy from his sleep, he looked around in a panic. He sighed heavily;to his relief, he saw that he was in his own bedroom. His simply decorated and cozy room. Not a hospital ward. And no spiders, let alone their webbing in sight.

He had had this particular dream--the spider dream as he referred it to his friends, to differentiate from his other bizarre dreams--for the last few days. Each time it had taken longer for him to wake, allowing him to gather more details about it. While the man had been in these dreams before, speaking was a new addition. But what language was that? It sounded like Latin, or at least something old like that. Mark only spoke English, and bits of Spanish that he learned in school; both of which were no help to figure out what the man had said.

He rummaged through his night stand and pulled out a spiral notebook. Grabbing a pen, he wrote down tonight's dream. He hoped he had the words correct and that he could find a good on-line translator that could help him make some sense of them. He put his dream journal back away and wiped the sweat from himself, before trying to go to sleep again.

A few hours later, Mark woke up again; he had no odd dreams or nightmares this time. As far as he could remember, it was just dreamless sleep, restful for his body but his mind was still groggy and on edge. He got out of bed slowly, and started his morning routine.

First, he showered. He was still groggy and he caught himself almost dozing off again as he stood motionless in the spray of the hot water. He toweled himself dry and got out of the shower. Wiping the steam fog from the mirror, he spent a few moments making odd faces and expressions at his reflection. He brushed at his hair haphazardly. He made a grimace at his reflection, and brushed it in a different direction. Not liking that, he ran the brush through his hair again. He never liked his wavy hair, or the unruly cowlick that happened whenever he had his hair cut short. Unfortunately, his office job necessitated a ″professional″ hair cut, and, thus, his daily battle with his hair. It used to be so much quicker when his hair was longer.

Perhaps it was just his tiredness, but he made more faces at the mirror and decided that he didn't like anything he saw. No, he didn't like what he saw at all today--not that he ever liked the way he looked, but today was particularly bad. The only thing he liked was his nose, and he was pretty sure that was only because his goatee drew attention from it.

Then, he took his medications--one for his allergies as springtime was hellish for him and another for anxiety. He smiled slightly at the thought that maybe he should take the anxiety pill first thing in the morning, before having his daily bout of self-disapproval.

He worked not far from his Manhattan apartment, in an engineering firm's accounts receivable department. It was rare that Mark spoke about his work; when he did, his friends would make over dramatic pantomimes, loudly ask how he could do such a boring and mundane job. Of course, it wasn't as if Tommy or Peter had ″glamorous″ jobs. Tommy was a courier for a law firm and Peter was "self-employed", but mostly he just collected disability pay and went to see a psychiatrist three times a week.

Even though he had psychiatric medications, Mark wasn't one for therapy and therapists. Peter, once an actor, was now effectively crippled by his paranoia, unable to perform in front of audiences or large crowds, let alone overcome the daily struggle to leave his own apartment.

Mark had recently begun to worry that there was something seriously wrong with himself, far beyond what his nagging worries and anxious thoughts. There were, of course, the nightmares; always vivid and almost always about some sort of constrictions or impeding death. And there always was the ″doctor″. He wasn't always in that guise, true, but it was always him. Middle aged, stern looking, with a full beard, the man in his dreams had never spoken before last night. And now that he had, he spoke in a language that Mark didn't know. That confused and frightened him; how could such a thing happen? .

From all that he had ever learned about dreams, it didn’t seem possible for something like last night's dream to occur. Unless, of course, what the man said was some gibbering nonsensical language conceived by Mark's subconscious or perhaps it was a riddle. The mind works oddly at times, trying to express your deepest fears and concerns through dreams, but it wasn't always clear; hiding behind symbols and inscrutable patterns. Mark remembered that much from introductory classes in psychology he had taken at college.

As soon as he could find the time, he intended to find out what, if anything, those words meant. He hoped it would be something simple; maybe those words were something Mark had heard once in a documentary or a movie. On the other hand--highly unlikely as it would seem--maybe he was somehow dreaming in a language that he didn't know. The idea of that alone was enough to cause a shiver to run along his spine. He thought that he would prefer the simpler, more reasonable explanation.

And, yet, what if it wasn't just his mind playing tricks on him? Could it be something worse, and not just strange dreams and restless sleep? He would have liked to be able to do nothing other than to mull these thoughts over. Mark had always been one to think problems through and try to see all the angles concerned. It had only occasionally proved to be useful, and it usually just resulted in him appearing to be indecisive and non-committal.

Those matters would have to wait until another time, though, as the pressing concerns of accounts receivable were weighing heavily on him. He smiled absentmindedly as he sat down in his cubicle and logged into his workstation. He took a sip of coffee and answered his ringing phone. ″Petersen and Jones Engineering, Mark Roberts speaking," he said.

″Hello, Mister Roberts," the voice on the phone said. ″Misters McNally and Cooper would like to know your availability vis-à-vis a lunch appointment.″

"Yes, I can do lunch today, Tommy. And your snooty businessman impression still needs work."

"Good, I'll be down by your building dropping a contract off around noon. I’ll make sure Pete's medicated enough to leave his apartment."

"I'm sure you don't have to do that," Mark said. "Just tell him that the government will be activating all the microphones in his apartment at noon. No need to get him all doped up and stupid."

"Yeah, you have a point Mark. I'll meet you two out front later."

Hanging up the phone, Mark concluded that at least today wouldn’t be totally dull. There'd be an entertaining lunch, and most likely on the house as Tommy would make sure to pick a place where he knew the wait staff. Maybe not for all three of them, but at least for himself.

The hours until lunchtime slowly passed, with Mark having to do the usual routine of calling vendors and customers to arrange payments and billing schedules. It was a fairly easy job, since the firm was itself financially successful, but also was lucky enough to have clients who diligently paid on schedule.

The whole while, he felt like someone was watching him. He caught himself glancing out his cubicle entrance; he even stood up once and looked all around the office. Even though he saw no-one or anything like a camera or other recorder, he still couldn’t shake the feeling. After his second cup of coffee at around 11:45 AM, he felt a mild pain that seemed to be centered behind his eyes.

He stopped looking over the invoices he was working on and rubbed his temples, while squeezing his eyes shut tightly. The pain lessened a bit, allowing his to return to work. Again, however, the feeling of being watched returned; this time it felt like someone was standing over his shoulder. Mark was sure he felt something breathing on the back of his neck.

He quickly turned around to see what was behind him. As he suspected, there was nothing there. Swiveling his chair around to face his desk once more, his foot caught on the small garbage can in his cubicle, making it clatter against his file cabinet. Lucia, who sat in the cubicle opposite his, looked up at the commotion with a puzzled expression. "Everything ok, Mark?" she asked.

Lucia Pietrangeli was somewhat attractive to Mark, but first and foremost she was a coworker; and that meant, to him at least, that she was off limits and not worth the hassle of thinking about it in that fashion. He was certain that had she not been a work associate she would be firmly in the attractive category, but of course, that would then mean that he would be unable to talk to her due to his quirky social anxieties. He sighed a bit at how messed up his brain was, before saying, "Yeah. I think I just had too much coffee. I’m a little jittery."

"You're always a little jittery, Mark. Do you ever relax?"

"Who has time to relax?" He glanced at his watch and noticed that it was almost noon. "I'm going to lunch," he said, adding, "Be back in an hour."

"You want some company?" Lucia asked.

"Can't today, I'm meeting with some friends." He stopped for a second, before saying, "We'll get lunch tomorrow, ok?"

"Sure thing," she said. "I get to pick the place this time though."

He stood up and grabbed his jacket, heading towards the elevators. As he waited for the elevator to arrive, he rolled his head from side to side with eyes shut. He heard the bell that signaled the elevator's arrival and opened his eyes, with a heavy sigh.

What he saw, however, was not what he expected. Instead of the familiar open elevator doors in the little lobby on the fifteenth floor of the Beakerman building, Mark saw a dimly lit vestibule with large cobwebs clinging to the vaulted ceiling. Spiders could be seen traversing the webbing, heading to and fro along the strands.

Where the open elevator doors would be was instead a yawning pit; the sight of which filled him with a rush of vertigo. He steadied himself and peered over the edge of the pit, trying to peer into its depths. He could see, faintly, some large form writhing therein.

In a panic, he turned his head, gathering in what he could of his surroundings. He couldn't see his coworkers, nor any of the drab office decorations or paintings, nor the various potted plants. Instead, there was only himself, the spiders crawling along their webs, and the writhing, pulsating form in the pit.

"Nunc vigila, Marcus," a voice said.

He recognized it immediately as the voice from last night’s dream. "Vestri semita plumbum in obscurum quod puteus."

He spun around to see where the man was, but as he did so he became dizzy. Stopping to steady himself, his vision darkened and the scene before him faded away.

When his senses became clear again, he was standing in the elevator lobby; the door to the elevator open before him and quiet soothing symphonic music emanated from within. He looked around, and to his relief there was no one there to have witnessed his odd behavior. This was getting out of hand now, weird dreams were one thing but hallucinations were an all together different concern. He hoped that maybe it was just the lack of sleep and he hadn't hallucinated, but briefly zoned out while waiting for the elevator. The thought that his mind was simply overtired and was causing him to have a daydream put him a little bit at ease.

He was still deep in thought when he emerged from the building and onto the sidewalk outside. Peter was already waiting outside, leaning against the building and smoking a cigarette.

They exchanged greetings and Mark leaned against the wall as well, waiting for Tommy to get there.

*


As usual, Tommy was late. He always ran late when he was delivering contracts, as they required him to wait for the receiving party's signatures and that gave him time to make small talk with the secretaries. He was fairly popular with them, always eliciting an easy laugh or smile.

This annoyed Mark, who had always found it difficult to engage easily in conversation with anyone, let alone women. He would often find himself taking shallow breaths and could feel sweat beading on his forehead; thankfully, the pill he took for anxiety helped but it didn't make it any easier for him. Mark was often at a loss for what to say next in a conversation with a stranger, fearing that he would offend them or anger them. The truth of the matter was that the only people he felt at ease with, at least for social situations, were Peter and Tommy.

He had known Tommy for what seemed like forever. They had grown up together in New Jersey and moved into New York City at about the same time, which was when Mark graduated from college and Tommy had dropped out of law school. It always amused him that Tommy had decided he couldn't bear to be a lawyer, but had no problem collecting a paycheck from them.

Peter lived in the same building where Mark's first apartment was. They clicked fairly quickly, sharing the common bond of questionable sanity. Further, at that time Peter was still actively acting in plays and kept dragging Mark to various cast parties and after show events. Unlike the other two however, Peter was well into his forties and was recognized from time to time for either one of the many plays he had been in or the television show he had been on in the 90s.

When Tommy arrived, they walked around the corner to a little Mexican place. The restaurant had good food and, more importantly for Tommy, his current love interest worked the lunch shift there. This guaranteed them a reduced bill, at the expense of Mark and Peter having to endure Carmen constantly coming over to their table to talk to Tommy.

During the meal, they made mindless conversation, which briefly touched upon politics, the hotness or non-hotness of the women walking past the restaurant, and how much all three of them disliked the selection of movies playing at the theater closest to their apartments.

After finishing his meal, Tommy excused himself from the table, going over to the kitchen entrance to talk with Carmen. Mark and Peter still had some of their meal left, so they assumed they would be finished by the time that Tommy was finished with his business.

"Something weird happened today," Mark said, nervously tapping his fork against his plate.

Taking a sip of his soda, Peter asked, "What?"

Mark answered, "I had some sort of hallucination, or maybe just a daydream. It was a new version of the spiders dream. It happened when I went to get on the elevators before."

"Buildings have spiders in them, Mark. That's not something to worry about."

Mark laughed, before saying, "The paranoiac is telling me not to worry about something bad happening to me."

"It's just spiders."

"No, it wasn't just that," Mark said. "The whole place took on a weird look, like one of those medieval churches or something. And, instead of the elevators, there was a deep pit with some thing at the bottom. I couldn't tell what it was, but I could definitely see it writhing about in the shadows."

"Really?" Peter asked. "Now that is worrisome I think. Hallucinations are serious stuff, Mark. I think you need to see a professional, I can see if my psychiatrist is taking on new patients if you'd like.″

Mark put a twenty dollar bill on the table and stood up. "Not doing that," he said, before adding, "I have to get back to work. Tell Tommy I'll catch up with him later."

Peter sat in silence, waiting for Tommy to get out of the back office. The entire time, he was thinking over what Mark had just told him. He knew about Mark having the "spider dream" almost nightly and how it was made him very frazzled. Peter could only wonder how he would be after a few days of seeing them even when he was awake.

*


Mark thought that he should go back to the restaurant and apologize to Peter for his outburst. After all, what if he really were going crazy? What would happen then? He grimaced at the thought of being committed to an institution or hospital, constantly being monitored and medicated.

It's just stress, he kept telling himself. Lack of sleep and the realization that he had just had another disappointing year in his disappointing life all culminating in this series of dreams and visions. Maybe it was his subconscious crying out for a change, a desperate plea for Mark to shake up his meaningless and empty life.

While he was afraid and hesitant to talk to therapist or psychiatrist about recent events, he felt that it was safe to confide in Peter. After all, how could Peter, who had his own ailments, be judgmental about it? How couldn't he understand Mark's fears of being institutionalized?

Mark still remembers the creepy, almost surreal, stories that Peter would sometimes tell about his time in a mental hospital. There was no way, no how, that Mark wanted to be anywhere near such a place.

Now that he was at the front entrance to his office building, making amends with Peter would have to wait, and Mark was certain that Peter would understand his reaction. After all, Peter occasionally freaked out and ranted at Mark and Tommy about black helicopters coming for them in the middle of the night; they always let it slide when Peter told them he forget to take his pills. Mark expected the same from his friend.

Monday, October 13, 2008

Generating Traffic

This review of Web Juggernaut showed up when I was searching around for ways to get visitors to this blog. I'm not trying to do the whole "niche blogging" thing to make money or anything, I just want to get my ideas on software and writing shared with other people.

Which, of course, requires visitors. It seems like a fairly easy link exchanging type program. I have no idea if it works or not, but I'm still doing my research.

I know that the best method of getting traffic is to have good solid content, but that takes time to develop and I am working on that. In the meantime, what programs or methods have worked well for you?

Sunday, October 12, 2008

Death of a Hard Drive

On Saturday, one of the hard drives in my near ancient Linux server failed. Even though I had back-ups of some of my data, I was lax and hadn't backed up some of the information for a few of the web sites that reside there.

So, until I can rebuild those web sites, I have to use the mod_rewrite features of Apache to temporarily redirect visitors to a working web site. This is done with the following entry in the virtual host information:


<VirtualHost>
ServerName www.stevecoursen.com
RewriteEngine On
RewriteRule ^(.*) http://blog.stevecoursen.com [R,NC,L]
</VirtualHost>


So, if you were trying to go to a different website, but ended up here, it's because I haven't restored or rebuilt the site you were trying to get to. It would also be the reason why no one was able to really get to this blog yesterday either, as the machine that failed is also my DNS server.

Friday, October 10, 2008

Official Gmail Blog: New in Labs: Stop sending mail you later regret

It's late night on a Friday, you've just come back from a party, and you get the brilliant idea to send an email to an ex. Never fear, Google's Mail Goggles are here.

It's an add-on that asks math questions to verify your sobriety during designated hours. If you answer the questions correctly, the mail will be sent.

Official Gmail Blog: New in Labs: Stop sending mail you later regret

Thursday, October 9, 2008

Encouraging Children to Write

Children can be surprisingly adept at making up stories. They do it all the time, when they lie or need to make an excuse for why they didn't clean their rooms. Schools don't actively encourage it enough, but creative writing can put all that story telling ability to good use.

  1. Read: Of course, the very first step in encouraging a child to write is to also encourage them to read. They need to read just about anything and everything they can both get their hands on and understand (so that means no War and Peace for the 1st graders!).
  2. Discuss: It works best when you've read the same book or article and can talk to them about it. Share your favorite characters or scenes; talk about what made you want to read to the end of the story. Being diligent about this will lead you to learn what type of fiction that the child likes.
  3. Read Some More: Inevitably, people write what they already like to read. After all, it's very difficult to write a good horror story if you don't like horror, let alone have never read any. Each genre of fiction has certain expectations and conventions that readers expect; in fact, they will feel outright cheated if one doesn't employ those conventions in some form or another. The only way to really learn what these expectations are and how to work with them, is to read.
  4. Brainstorm: Buy them a journal or a notebook to write in. Encourage them to write their ideas down and to try to plan out their stories. Once a week go through it with them, and brainstorm with them to help flesh a basic idea out into a full story. Make sure that when you do this, you don't supply any ideas though; encourage their creativity, don't write vicariously through them.
  5. Support: Hopefully, they will like a type of fiction that you are comfortable with, so that you can be a supportive critic of their work. Most writers tend to be shy about their works, nervous that they either have no talent or that no one will like the story they're telling. Print out their stories and make them into home-made magazines. Start up a blog and post the stories there for others to read -- a community like MySpace is good for this because you can limit who can read the blog.
  6. Feedback: The most important thing to remember is that when you give feedback on their work, always be encouraging. Young writers tend to be easily dissuaded from sharing their works if they get negative feedback. Be sure that you focus on things like grammar and spelling; even with computers, grammar errors can slip through and make a piece of fiction incomprehensible.


With these 6 steps, you should be able to get your child to write not just fiction that they enjoy, but hopefully that they can share proudly with the world and have others enjoy as well.

Wednesday, October 8, 2008

Ruby On Rails Development

Over the past few years open source software, web platform and technologies have taken stake of web development and web application development. With Ruby on Rails hype in IT industry we have seen proportionate increase in performance and scalability problems. Ruby on Rails was extracted from Basecamp by David Heinemeier Hansson, is a framework for web application. Ruby on Rails development India offers Ruby on Rails offshore outsourcing web development and is based on open source web platform, LAMP. Ruby is object oriented programming language, it is blend of different languages - it has taken concept from Smalltalk, ease to use from Python and reality and flow from Pearl. Rails is well stack, comprehensive open source framework for developing database supported web applications, dynamic websites using model view controller (MVC) methodology.
With your database and web server, the Rail web development environment helps you develop complete, simple web application with rich functionality and interactivity. Because of the flexibility it provides Ruby on Rails is well suited for e-commerce development, content management, oscommerce, collaboration and online social communities. Since Rail works well with wide range of web servers and databases it is really easy to deploy web solutions using Rails.

Ruby on Rails (RoR) development main features include Model View Controller architecture that separates data from logic i.e. presentation layer and helps in organizing application program. RoR database access library simplifies data handling. Rails framework consists of extensive AJAX library, Ruby uses this library to generate AJAX code and the required Java script is automatically generated.

Let us discuss in brief Ruby on Rails framework, it includes following packages: ActiveRecord, ActiveResource (Active Web Service Package), ActionPack, Active Support, ActionMailer. These packages can be customized by adding plug-ins and extending existing functionalities of these packages.

Ruby on Rails outsourcing companies help to develop database driven web applications. Flickr is one of the best example of the web application developed for sharing photos on web. With ruby on rails, developers are able to design web applications that are simple and logical. As database driven websites share common set of parameters, rail handles code for connecting application to database; at the same MVC for application development separates data from logic. Scaffolding technology of Rails framework creates the skeleton application that contains model, view and controller components and controller performs all the application actions.

In brief, Ruby on Rails development is used for providing object oriented and component based web application development services. Ruby on rails outsourcing companies in India provide Ruby on Rails developers, outsource Ruby programmers to clients globally.

Rakhi, is a SEO strategist, SEO copywriter, SEO executive at open source development company in India outsourcing Ruby on Rails development. Ruby on Rails development in India offers offshore open source development, open source software solutions, offshore Ruby on Rails offshore outsourcing, Ruby on Rails development, outsourcing Ruby on Rails development, Ruby on Rails CMS, open source software solutions, open source development India. We provide simple, logical and most reliable, high quality solutions to global clientèles.

Looking for open source web design development, open source software solutions, CMS solutions, drop us mail at: webmaster@open-source-development.com

Article Source: http://EzineArticles.com/?expert=Rakhee_Chowdhary

Note: I'm short on time this week, so I'm half-mailing it in. I'm re-posting interesting articles that I find.

Monday, October 6, 2008

Singleton Pattern for Python

In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist.


class Singleton(object):
instance = None
lock_obj = threading.RLock()

def __new__(self, *args, **kwargs):
return self.get_instance( *args, **kwargs )

@classmethod
def get_instance(clazz, *args, **kwargs):
with clazz.lock_obj:
if clazz.instance is None:
clazz.instance = object.__new__(clazz, *args, **kwargs)
clazz.instance.init(*args, **kwargs)
return clazz.instance

def __init__(self, *args, **kwargs):
super( Singleton, self ).__init__(*args, **kwargs)


def init(self, *args, **kwargs):
pass

class Test(Singleton):
def init(self, *args, **kwargs):
#do initializations here, not in __init__
pass

print Test()
print Test()


The output of printing the value of the result of the "creating" the 2 Test objects will show that actually only one Test object was created.

This pattern is needed very often in Python, although when it is needed it addresses the problem very handily.

Note: this is code based off some searching earlier this year. I no longer remember exactly where I found the original that I based this work off of.

Saturday, October 4, 2008

Associated Content

I've heard good things about Associated Content, where you get paid for publishing content and articles. So, I submitted two pieces of flash fiction (short stories of up to 2000 words). They're now available for viewing.


Timmy's father shipped out on active military duty the previous Christmas. Before he left, he gave Timmy a collection of little green army men; most of which were his favorite toys when he was younger.

Toy Soldiers Off to War
A piece of flash fiction (a short story up to 2000 words).
View more »

The Montoya was berthed in Fueling Bay 2-A. James Sandersen had the annoying habit of liking to run the ship down below manufacturer's recommendation on fuel levels. He also ran the ship past suggested maintenance schedules, but that was due to finances more than any other factor. Sandersen always insisted that the shipbuilders were in a cartel with the fuelers, but that was neither here nor there.

Deal Done Bad
A piece of science fiction flash fiction (a short story of up to 2000 words).
View more »

Friday, October 3, 2008

EVE Online's Stackless Architecture

I just saw this article about EVE Online's Server Model. Very interesting and informative read, and a testament to Stackless's reliability and usability.

Weekly Roundup

This week has seen some interesting news in the Python world.
  • In particular, the release of Python 2.6, with support for json and a new multiprocessing paradigm.
  • In my research for other projects, I ran across an older article by the ineffable effbot about thread synchronization.
  • One of the more interesting, and sometimes confusing, parts of Python is list comprehensions, explained in good detail in this article on comprehending list comprehensions.
  • I don't often need to write a parser, but the ideas presented in the "Zen of Parsing" seem very useful for those rare instances.
On the other hand, not everything I did this week was programming related.

Thursday, October 2, 2008

Perspective Broker Authentication for Stackless Python



Twisted Matrix's Perspective Broker is, to me at least, the main compelling reason to use the entire framework. It's also an area that is lacking in documentation that is usable to a newbie to the framework.

One of the things provided by the Perspective Broker is an authentication framework, based around the concept of an avatar. We're going to create a Perspective Broker authenticator that is more complex than what is presented in the Twisted Matrix documentation.

In one of the projects I worked on, we needed to have a central authentication server, to which all the other object brokers would authenticate against. Due to the way that Twisted operates, a user needs to authenticate against the broker that they are currently connected to. We need to build a authenticator that can authenticate for itself, or if needed, recursively authenticate against another server.

To achieve this goal, we run into the first hurdle, Twisted doesn't pass a meaningful password around. This changes the order of authentication slightly then, as we now need to authenticate against the main authenticating server first. That server then gives us a cookie, known as authentication_cookie in the code below. This cookie is good for this login session with the main authenticator. When connecting and authenticating against any other broker in the system, we pass the username and this cookie as our credentials.

class UsernamePasswordDatabaseChecker:
interface.implements(checkers.ICredentialsChecker)

credentialInterfaces = (credentials.IUsernamePassword,
credentials.IUsernameHashedPassword)

def __init__( self, login_service ):
self.login_service = login_service

def passcheck( self, account, credentials ):
if not account:
return failure.Failure( NoSuchAccount( ) )
c1 = credentials.checkPassword( account.password )
c2 = credentials.checkPassword( account.authentication_cookie )
if c1:
return login_server.MasterAuthenticationStatus( account.username,
account, 1 )
elif c2:
return login_server.MasterAuthenticationStatus( account.username,
account, 0 )
elif not c1 and not c2 and account.authentication_cookie:
return failure.Failure( AuthenticationCookieMismatch( ) )
elif not c1 and not c2 and not account.authentication_cookie:
return failure.Failure( InvalidPassword( ) )
return failure.Failure( NoSuchAccount( ) )

@reactor.deferred_tasklet
def store_auth_cookie( self, auth_status ):
bcr = reactor.blocking_tasklet( self.login_service.callRemote )
return bcr( "store_authentication_cookie", auth_status )

@reactor.deferred_tasklet
def requestAvatarId(self, credentials ):
if hasattr( self.login_service, "callRemote" ):
bcr = reactor.blocking_tasklet( self.login_server.callRemote )
acct = bcr( "get_account", credentials.username )
self.passcheck( acct, credentials )
status = bcr( "account_status", acct )
rv = self.store_auth_cookie( status )
return rv
else:
rv = self.login_service.authenticate_account( credentials )
return rv

We use one of the function decorators from when we first started integrating Twisted into Stackless python, the deferred_tasklet. If you haven't read that article, the deferred_tasklet decorator wraps the function to run in a seperate Stackless tasklet, while still returning a Deferred that can be used by the rest of the Twisted machinery.

The referenced member login_service is a straight-forward object that implements the function authenticate_account. If the credentials it is passed are good, it returns an object -- this object is the avatar required by the Perspective Broker. If the credentials are bad, it returns None, which then gets translated into an appropriate remote exception.

The core ingredient in this is whether or not UsernamePasswordDatabaseChecker's member login_service has a member method callRemote. In this scenario, we make remote calls to do the authentication. We use another one of function decorators, blocking_tasklet, to do this so that our code can remain synchronous in style.

All in all, using Stackless tasklets to implement this setup results in less lines of code, and code that is straight-forward and easy to understand. The purely Twisted incarnation of this setup result in a crazy amount of nested callbacks that were very difficult to follow during initial testing, let alone a few months later.

The examples for login_service can be provided, if anyone wants, I just need to dig through the CVS repository to find them.

Wednesday, October 1, 2008

Stuff in the refrigerator

Now that we've looked at the stuff in my living room, let's wander over into the kitchen and check out the fridge.

1. Grapes: There's some other fruit in there as well (peaches, strawberries, and some pineapple). But I like the grapes, especially the seedless ones. You can just keep popping them into your mouth, one after the other after the other. Before you know it, you've eaten way more than you should have. My rating: A+
2. Milk: Combined with some chocolate chip cookies, this is my ideal after-dinner treat. Oh, and it's useful for coffee and cereal. But, really, it's all about combining it with cookies. My rating: A
3. Diet Dr. Pepper: Of all the different sodas I've tried, this is the one that tastes least like diet soda. This, of course, is important as some diet soda ends up tasting horrible reminding you that you've opted for lower calories over good taste. It also happens to be my favorite mixer with certain alcohol. My rating: A
4. Salad: I don't usually eat all that healthy. I mean, I try to. I want to. However, I happen to like the way certain foods -- usually the ones that are not good for you at all -- taste. I do like salad though, particularly simple just a simple combo of tomatoes, lettuce, and radishes. My rating: B+
5. Southern Comfort: I haven't drank Southern Comfort straight up since college, and it was the leading cause of some of my stupider decisions. I do like to, occasionally, mix it with the aforementioned Diet Dr. Pepper into a very tasty adult beverage. My rating: A+

Tuesday, September 30, 2008

A quick update...

I planned on having an entry tomorrow showing a more in-depth example of combining Twisted with Stackless python, but it's taking a little longer than expected to get all the pieces together. The example will be using what is in my opinion the most useful part of Twisted: the Perspective Broker. I have several working systems that utilize it, but pulling out just enough to demonstrate how to use the PB with Stackless is proving a little troublesome.

It should be ready by Thursday.

Multi-Threaded Twisted / Stackless Integration




Another way to integrate Twisted with Stackless python, is to use multiple threads. One thread handles Twisted's reactor while Stackless tasklets run in at least one other thread. This lowers the deterministic nature of Stackless, but for certain conditions may be more effective than trying to integrate Twisted and Stackless into a single thread. Communication between the threads is handled through a channel, which according to the documentation for Stackless python is thread-safe.

the_channel = stackless.channel( )

def a_func( *args ):
print "a_func:", args
return args

def dispatch( d, func, *args, **kwargs ):
d1 = defer.maybeDeferred( func, *args, **kwargs )
d1.addCallback( lambda x: reactor.callFromThread( d.callback, x ) )
d1.addErrback( lambda x: reactor.callFromThread( d.errback, x ) )

For our example, we'll be calling a_func to run in the Stackless thread. This is handled through the helper function dispatch. The result of the function will be wrapped up in a Deferred. Through the reactor's callFromThread method we'll be able to fire the callback chain inside the thread running the main Twisted reactor loop.

the_channel is our cross-thread communication channel, through which the requests for function invocation will be passed.

def stackless_dispatcher( chan ):
while True:
try:
d, func, args, kwargs = chan.receive( )
t = stackless.tasklet( dispatch )
t( d, func, args, kwargs )
print threading.currentThread( )
stackless.schedule( )
except:
break

This is the main loop of the Stackless thread. This method loops until an error condition occurs -- in this simplified version that is enough. It blocks on the main channel, until it receives a function, function arguments, and a Deferred that will be fired upon function completion. It then creates a tasklet to run the function in.

def call_in_stackless( chan, func, *args, **kwargs ):
d = defer.Deferred( )
t1 = stackless.tasklet( chan.send )
t1( (d,func,args,kwargs) )
stackless.schedule( )
return d

This function is called from within the reactor's thread to cause a function invocation inside the Stackless thread. Because Stackless complains about deadlock when sending on channels, we have to create a tasklet to send on the main channel. The function, arguments, and a newly created Deferred are sent via the channel and the Deferred is returned from the function. Ultimately, this Deferred will have it's callback chain fired so at this point, traditional Twisted-style programming can continue.

def test( chan ):
print threading.currentThread( )
d = call_in_stackless( chan, a_func, 1 )
d2 = call_in_stackless( chan, a_func, 1, 2 )
dl = defer.DeferredList( [ d, d2 ] )
dl.addCallback( lambda x: reactor.callLater( 0, reactor.stop ) )
def ender( x, chan ):
t = stackless.tasklet( chan.send )
t( x )
stackless.schedule( )
dl.addCallback( ender, chan )

reactor.callInThread( stackless_dispatcher, the_channel )
reactor.callLater( 0, test, the_channel )
reactor.run( )

This is just a test of the premise. It should operate as expected, with a_func being invoked twice inside the Stackless thread before the reactor is stopped. We force a shutdown of the Stackless loop by passing a single argument through the channel -- since the receiving side is expecting a 4-part tuple this will cause an exception and stop the loop.

This form of integration does allow for some more concurrency than the previously discussion integration method. While we have to worry about Python's GIL (global interpretor lock) cutting down our actual concurrency, if the application is heavily I/O-bound this is not much of an issue since the GIL is released whenever control passes into the Twisted's reactor loop.

Monday, September 29, 2008

Bestsellers and Book Sales Expectations

Note: I found the following while surfing and googling around. The article's terms of use allows for copying it, as long as I maintain the proper attributions.


Most new authors have no idea how book sales happen or what numbers to expect. A typical successful book from a major publisher sells between 20,000 and 40,000 copies. Healthy book sales from a smaller publisher may number at least 5,000 copies, whereas a self-published book may be considered promising if it sells as few as 1,000 copies to a wide audience.

Set your sales goals high but your expectations lower. Obviously you want high sales for you book; otherwise, why do all the work? But be clear about your vision. If you plan to author a book for your own seminar business, your expectations will necessarily be different from those of the author who wants to become a world-class speaker and subject-matter guru. Clearly a book about diets will have broader market appeal than a book on corporate strategic planning.

Your ability to drive book sales will also depend on the name recognition you’ve already established. Someone like Dr. Phil McGraw can realistically expect his next book to sell millions of copies regardless of the subject matter. How’s your name recognition?

Most people are surprised to hear that less than half of book sales each year are through bookstores, leaving other possibilities for authors to pursue.

Many new authors just assume their book will appear in bookstores. If the book is self-published, it is very unlikely you will be able to crack the bookstore market; therefore, it will be important to consider:

* Sales through your own Web site
* Sales through Amazon.com and BarnesandNoble.com
* Sales through other Web sites and affiliate programs
* Sales through print catalogs
* Sales to specialty markets for premium incentives (organizations and corporations)
* Sales to mass merchandisers or other retailers

Almost the only way to get your book into national bookstore chains is to be published by a traditional publisher. They have the distribution methods in place to make this possible.

You may choose to self-publish and work on sales through some of these non-bookstore channels, get to credible sales figures, and then approach a traditional publisher to finally hit that desirable bookstore market.

If you sell your own book, you know exactly how many books you printed, how many have been sold, and how many are left to be sold in the printing.

Oddly enough, when books are published by traditional publishers and go through the bookstore system, there are very few avenues open for authors and even publishers to track "real" sales of books. The Bookscan report from Neilsen Broadcast Data Systems, available since 2001, provides weekly sales by the major book retailers. But only the very largest companies can afford this expensive service. It is virtually impossible to estimate the real sales of a book from the quantities that are shipped to the stores. Remember, all "sales” to bookstores are made with a long-established, full-price return policy anytime. That means all the books could be returned to you, even a year later. Major publishers expect overall return rates of 20 percent to 30 percent, but individual books can be much, much higher.

When your book is returned, it doesn’t mean that someone bought it, didn’t like it, and sent it back through the bookstore. Far more likely, it was never sold in the first place, and the bookstore returned it to the distributor after sixty to ninety days.

You will see sales numbers on your royalty statement, but generally there is also a reserve for expected returns as well.

If your book is published by a traditional publisher or printed by Lightning Source, you can call the distributor Ingram’s sales tracking phone number, 615-213-6803, to hear about sales for both the previous week and last year.

It seems that most authors these days say their book is a best seller, and that’s because there is no established, objective criteria for what that means. There are roughly forty national and regional best-seller lists in the United States. The New York Times’ list is probably the most well-known and respected. Another one that is well-known, especially inside the publishing industry, is provided by Publishers Weekly (PW). In 2005, 442 adult titles were declared best-sellers, according to the Publisher’s Weekly compilations.

Some best-seller lists such as those belonging to Publisher’s Weekly and USA Today are based on national surveys, with others on much less objective criteria. The New York Times bases their list on a poll of both chain and independent bookstores. The list from the American Booksellers Association polls only independent bookstores. The Los Angeles Times polls thirty bookstores in the Los Angeles metropolitan area to compile its list.

Only eight self-published books have made it to number one on the Publishers Weekly bestseller list.


Copyright (c) 2007 Gail Richards

Sunday, September 28, 2008

Sunday Funnies

They're not necessarily new, but these are some strips I like.






The Order of the Stick (doesn't allow hot linking :( ).

I know, no great new findings here, but I thought it'd be nice to share to those few out there who may not actually have seen either of these strips before.

Saturday, September 27, 2008

Observer pattern for Python



The Observer pattern is mainly used to implement a distributed event handling system. The primary objective of this pattern is to provide a way to handle run-time one-to-many relationships between objects in a loosely coupled arrangement.

In this configuration, the Observable object doesn't know anything more about it's Observers than a very limited interface. The Observable needs to provide a wide interface for allowing other objects to gain access to it's current state.

The event from the observable object's point of view is called notification and the event from the observers' point of view is called update.


class Observable( object ):
def __init__( self, *args, **kwargs ):
super( Observable, self ).__init__( *args, **kwargs )
self.__dirty = False
self.__observers = weakref.WeakKeyDictionary( )

def attach_observer( self, obs ):
if obs not in self.__observers:
self.__observers[obs] = 1
return self

def detach_observer( self, obs ):
if obs in self.__observers:
del self.__observers[obs]
return self

def set_dirty( self, d ):
self.__dirty = d
return self.__dirty

def is_dirty( self ):
return self.__dirty

def notify_all( self ):
for observer in self.__observers.keys( ):
observer.observer_update( self )

def notify_check( self ):
if self.is_dirty( ):
self.notify_all( )
self.set_dirty( False )
attach_observer and detach_observer maintain the list of Observers that are interested in this object. After any change in state, notify_all should be called. If this state change is part of a larger transaction, the combination set_dirty and notify_check should be called.

If you're also using Stackless python, you may want to have notify_all use the event-loop mechanism we've previously discussed.

class Observer( object ):
def __init__(self, *args, **kwargs ):
pass

def observer_update( self, object ):
pass
The Observer object is very easy to implement. Really, only it needs observer_udpate defined since that method is called by Observable during notify_all. The observed object passes itself as the argument to observable_update so that the observer knows which of the objects it currently is observing has been updated.

NewNovelist Review




I stumbled across this software package during a google search on tools for writers. I bought it and installed it after doing some more research about it.

Even though I tend to be a "pantser" when it comes to writing, I went through the dialogs and screens. I won't make any grandiose claims about it, but I found that after I had spent a few hours following the wizards, I had a much better and firmer grasp of where I wanted my last project to end up.

It made me think about things like character arcs and other details of story development that I usually don't spend much time planning. While that tactic worked for me in the past, it was proving difficult on my last project -- the great swamp of the middle of the novel -- that using this software helped me plan my way past.

Its not going to turn you into a novelist without you doing the legwork, but if you really want to write a book and are willing to put in the work to do it, then NewNovelist will help you.

My Rating: A

Friday, September 26, 2008

Weekly Roundup

So, it's Friday, and here we go with a small handful of YouTube clips I watched this week:





Complete with bad-ass jazzy Samurai gonna kick yo butt music.



Yeah, I'm still digging the new Metallica album.

Thursday, September 25, 2008

Event-based Programming for Python


Oftentimes, you need to have objects that communicate with each other via events. This is a very useful setup, for example, in a GUI -- where these events represent things like mouse clicks, key strokes, or button presses. That's not what I developed these classes for, since I was more interested in simulating things and the event system seemed like the most natural fit, but the recipe is still relevant to other event handling needs.

We're going to build upon earlier discussions, most notably about Stackless event loops by adding in some concrete examples of using that recipe.

The Observer pattern strikes again, as I'm defining the relationship between the event generator and the event listener as one of Observable and Observer. We'll make use of the channel_processor function decorator described in Stackless event loops.

class EventObserver( object ):
def __init__( self, *args, **kwargs ):
super( EventObserver, self ).__init__( *args, **kwargs )

@channel_processor
def event_transieve( self, *args, **kwargs ):
evt = kwargs.get( 'data', None )
self.process_event( evt )

def process_event( self, event ):
pass

def event_notify( self, event ):
self.event_transieve( event )

This is straight-forward enough. The only trickery (if you could call it that) is in the event_transieve method. And all that does is take whatever is passed as the keyword argument data and call the method process_event. In this base class implementation, that function does nothing.

One bit of niftiness does occur, however, when the event_transieve method is invoked. Through the use of function decorators (and therefore transparent to the calling client) this method actually spans across tasklets, granting some semblance of concurrency.


class EventObservable( object ):
def __init__( self, *args, **kwargs ):
super( EventObservable, self ).__init__( *args, **kwargs )
self.__event_observers = weakref.WeakKeyDictionary( )
self.__events = [ ]

def attach_event_observer( self, obs, level=1 ):
if obs not in self.__event_observers:
self.__event_observers[obs] = level
return self

def detach_event_observer( self, obs ):
if obs in self.__event_observers:
del self.__event_observers[obs]
return self

@channel_processor
def dispatcher( self, *args, **kwargs ):
data = kwargs.get( 'data', None )
wlist = []
for key in self.__event_observers.keys( ):
val = self.__event_observers[key]
seok = SortableEventObserverKey( key, val )
heapq.heappush( wlist, seok )
while len( wlist ):
obs = heapq.heappop( wlist )
obs( evt )

def dispatch_event( self, event ):
self.dispatcher( event )
return event
Now, we can safely ignore the attach_event_observer and methods -- they only exist to implement the Observer pattern. The only method we really care about at the moment is dispatcher.

In this method we simply loop over all the currently registered observers, invoking (ultimately) their event_notify method. If you don't see how that happens, just be patient and wait until we look at the SortableEventObserverKey helper class and it's definition of the __call__ method.

class SortableEventObserverKey( object ):
def __init__( self, kval, weight, *args, **kwargs ):
super( SortableEventObserverKey, self ).__init__( *args, **kwargs )
self.__value = kval
self.__weight = weight

def __cmp__( self, other ):
return cmp( self.__weight, other.__weight )

def __call__( self, event ):
return self.__value.event_notify( event )

def __repr__( self ):
return "%s, %s" % ( self.__value, self.__weight )

Now, I hate that I had to throw something like that into the discussion. The helper class only exists to make the comparison functions easier when using the heap queue. For anyone unfamiliar with heaps, a heap ensures that the highest weighted object is at the front of the queue and will be the first one taken out of the structure.

class EventParticipant( EventObservable, EventObserver ):
def __init__( self, *args, **kwargs ):
super( EventParticipant, self ).__init__( *args, **kwargs )
event_manager = kwargs.get( "event_manager", "events" )
self.event_manager = pytypes.get_event_manager( event_manager )

def generate_event( self, event_type, *data, **kwargs ):
evt = self.event_manager.create_event( self, event_type, *data, **kwargs )
return self.dispatch_event( evt )

Here's the easy class to implement. It defines the EventParticipant, which is both the Observable and the Observer. This is, utlimately, the class that I extend for my simulations since my program domain requires for the objects to both generate events and be interested in other object's events. Simply extending from this class gives you that ability in a nice, clean, and concurrent fashion (or, at least as concurrent as Stackless gets you).

Wednesday, September 24, 2008

Things on my living room floor...

To continue with the theme of "Stuff in Steve's Apartment", I'm now going to survey items found in my living room. To qualify, they must in some way or another, be in contact with the floor (which, by the way, is a nice hardwood floor that just cries out for you to slide on when wearing socks).

1. Kramer electric guitar: I don't know the model number, as it was a gift from a friend when he was moving out of his ex-girlfriend's place. He didn't know how to play it very well, so he handed it off to me; not that I'm really any better at it. I know some scales, and a bunch of chords though. And I can play a mean "Bad to the Bone" and "Creeping Death". Yes, I know the songs aren't related to each other, but my musical tastes are all over the place. Rating: B+ (has an electrical fault in one of the pickups, so the sounds fades at times)

2. Yamaha FG720SL acoustic guitar: Got this one as a Christmas present. Originally a left-handed guitar, I restrung it as a right-handed guitar. I'm sure that's against some rule in the guitarist's rule book. On this I usually just exercise my knowledge of chords, and play "Horse with No Name" and/or "Wish You Were Here". I'm sure my neighbors are sick to death of those songs by now. Rating: A+

3. Peavey TKO 80 amplifier: Something else that my neighbors must really love. I try to keep the output level low. Really, I do. My daughter occasionally will play with the dials when I'm not paying attention though, and then, at some point, later I'll turn it on and it's reverb and distortion city. Rating: B+ (don't use it enough to get a higher rating)

4. La-z-boy Couch: I love this thing. The end seats recline. It's very comfortable, and I can fit on it when I lay on it and stretch out. Rating: A+

5. Dell PowerEdge 400SC: This is my web server, mail server, and FTP server. It runs Linux (an older version of Fedora actually) and a whole bunch of custom-build packages and programs. It's the outlet for my inner computer geek. Rating: A

Unlike with the stuff on my bookshelf, I didn't move these items in anyway before reviewing them -- some were too big (the couch) and others, well, moving them would have made writing this entry difficult (the Linux server).

Later in the week, I'll be reviewing stuff in my rerigerator. (I actually have to go food shopping first, as there's nothing to review at the moment.)

Tuesday, September 23, 2008

Special Price on E-book Version of Path Into Darkness


Path Into Darkness e-book

For the next week (until 4pm, Tuesday September 30, 2008), the price for the e-book download version of Stephen Coursen's Path Into Darkness is reduced to $2.95.

Any blogger interested in doing a review of the book, can contact me in the comments section and I'll get them an e-book for review purposes.

Stackless Event Loops


This is a follow-on article to Stackless Python Meets Twisted Matrix. This time how to use function decorators to turn a ordinary looking function in a looping event dispatcher. Useful for the Observer design pattern.

Through the syntactical power of decorators, one can can convert any function into a continuously run event loop. This utilizes Stackless Python, which has been discussed in earlier articles on not only this web site, but many many others as well.

The premise behind this event loop is this: a tasklet runs and dispatches incoming "events" to a handler function. To the outside caller, it appears to be a regular function call, but the mechanisms provided by the decorator allow the execution of the "event handler" to be run in a seperate tasklet. If desired, this premise can be extended further to allow for the event loop to run in its own thread.

First, let's look at the class that does all the heavy lifting.
class ChannelProcessor:
def __init__( self, action ):
self.channel = stackless.channel( )
self.action = action
self.running = True
self.process( )

def stop( self ):
self.running = False
self.channel.send( 1 )

@blocking_tasklet
def __call__( self, *args, **kwargs ):
c = stackless.channel( )
self.channel.send( (c,args,kwargs) )
rv = c.receive( )
if isinstance( rv, failure.Failure ):
raise rv.value
return rv

@deferred_tasklet
def process( self ):
while self.running:
vals = self.channel.receive( )
if len( vals ) == 3:
c,args,kwargs = vals
d = defer.Deferred( )
d.addBoth( c.send )
_wrapper( d, self.action, *args, **kwargs )
else:
self.running = False

This code makes use of the decorators described in an earlier article, available here. As you will notice, the core of the event loop is contained in the process function, which runs in it's own tasklet (due to being decorated by the deferred_tasklet decorator). It doesn't matter if you aren't using Twisted for this code to work, although you will need Twisted installed for it to run (unless you change the mechanices of deferred_tasklet).

process
simply loops until told otherwise (via the stop method), receiving data from it's channel. If the data is a tuple of 3 items, it calls the original function (stored in the action member). Return value from the event handler is sent on a channel, which we received as the 1st element of the tuple.

An outside caller enters into this mechanism via the __call__ method. This method creates a new channel, and then passes that channel, and the parameters it was called with along the object's channel. It then waits for data to be sent back to it. After a quick look at the data returned, it either returns the data through the traditional means or raises an exception (if it received an exception).

Now, for the decorator:

@decorator
def channel_processor( f, *args, **kwargs ):
func_obj = None
if type( f ) == types.MethodType:
target = f.im_self
target_name = f.func_name + '_cp'
if not hasattr( target, target_name ):
func_obj = ChannelProcessor( f )
setattr( target, target_name, func_obj )
else:
func_obj = getattr( target, target_name )
elif not hasattr( f, "_cp" ):
setattr( f, '_cp', ChannelProcessor( f ) )
func_obj = f._cp
else:
func_obj = f._cp
return func_obj( *args, **kwargs )

Here, we create a ChannelProcessor object and stuff it into the calling function's member list (as a member named _cp). If it already exists, great. In any case, we then call the object, which will lead us into the __call__ method shown above.

A special case is made if we are an object's method, instead of a regular function. This does not happen in the regular use-case of a decorator (when using the @decorator_name syntax). It only happens when we do something like:

class A:
def __init__( self ):
self.func = channel_processor( func )

def func( self, *args ):
print "Here i am with arg list:", args

You use this method if you need to have each object having it's own tasklet that handles events. Using the standard decorator syntax results in each function having it's own event handling tasklet.

I tend to use the per-function methodology, but as usual, your mileage may vary.

Monday, September 22, 2008

Horses for courses....

Many years ago, when I was still in high school, my parents bought a chunk of undeveloped land in Montana. A few years ago, they retired, bought another, smaller chunk of land in Montana. They moved out west and started up a small ranch.

My daughter spends every summer out there (yay! mini vacation for me!) and has become quite adept at riding and other ranch activities. During her trip this year, she fell off one of the mares and cut her arm up pretty good on some barbed wire fencing. She's quite alright now, and in fact brags about how tough she is when showing off the scar.

Fast forward to yesterday. My mother called and told me that my father fell off of one of the horses (a stallion aptly named Scar). He cut his head open, had to get some stitches and staples. Additionally, he had a level 2 concussion which is causing him the usual side effects of concussions (forgetfulness, nausea, problems sleeping).

So, I decided to give a plug the website for their ranch business, Peak Performance Quarter Horses. I'm involved in the hosting of the site, but had nothing to do with the design.

Anyways, godspeed on my father's recovery.

Sunday, September 21, 2008

Stuff on my bookshelf

I'm picking 5 things off my living room bookshelf (ok, so they're already picked off the shelf ... I did do some footwork before I started to type this). Let's give them a quick review, shall we?

1. Diary of a Wimpy Kid: This isn't my book. Honest. My daughter loves it. She talks about it constantly, in that way that only ten years can. At her school's book fair last week, she bought the Diary of a Wimpy Kid Do-It-Yourself Book. She hasn't done anything with it, but she sure keeps talking about it. My rating: n/a. Daughter's rating: A+

2. The Light Fantastic: The first Terry Pratchett book I bought, because I had read a review of it in an old Dragon magazine. Yes, I'm that much of a geek -- no need to talk any further about it. Very funny book, as just about everyone who I've ever lent it to will insist. Skewers that highfalootin' fantasy genre, which can get a bit full of itself at times. My rating: A+

3. Another Fine Myth/Myth Conceptions 2-in1 (Myth 2-in-1): Another book I bought based off of a review I read in Dragon magazine. Yes, yes, I know. Geek. Anyway, very good stuff here, very ... uh, punny. Re-read it last year after the author, Robert Asprin, passed away. My rating: A

4. Colloquial Russian: The Complete Course for Beginners (Colloquial Series): An odd selection off the shelf. I was, at one time or another, a linguistics major in college. I picked up all sorts of language books -- German, Latin, Russian, Danish, Old English, even Sanskrit. Eventually, I wandered over into the world of computer science, where my fascination with languages continued on with books on Java, Python, C, C++, and Perl. Once a linguaphile, always a linguaphile. My rating: B+

5. The Path Into Darkness: Hey, the Web wouldn't be all about shameless self-promotion, if I didn't mention this book. Yes, I wrote it. I also have a hardcover copy of it on the shelf, but since I'm only doing quick reviews on 5 items, I choose the paperback version. I like it. Hell, if I didn't like it, I wouldn't have finished writing it, re-reading it, and editing it. It's self-published, which I know some people dislike, but there's a very good reason for that -- but I'm not goind to tell y'all what that is. My rating: A-. (Ha! You expected me to give myself an A+, didn't you? C'mon, fess up...)

Well, there you go ... 5 items off the shelf, reviewed, and then they'll be going back onto the shelf a few minutes after I click on the "Publish Post" button.

Stay tuned for another riveting chapter in "Stuff In Steve's Apartment" continues...

Saturday, September 20, 2008

Metallica's Death Magnetic is ... well ... pretty damn good.





This isn't usually a music review site, but I picked up Metallica's new album, Death Magnetic this week.

I was skeptical, what with having been disappointed by St. Anger. There was a lot of hype surrounding this one, and how it would be a return to their older sound. Personally, I liked Load and Reload (truth be told, I preferred the latter).

I popped the CD into my car's player and listened to it on the drive to and from work. Then again did the same the next day. There's a lot of goodness in the tracks, although the quality of the sound is ... poor. There are four "pure good" songs on the album, which I've taken the liberty of putting into the Amazon MP3 player so you can get the feel for them.



  • The opening track, "That Was Just Your Life", is incredibly good. Fast, crunchy guitar. Interesting singing.
  • The first single, "The Day That Never Comes", starts slow and ends fast. It reminds me somewhat of something like One or Fade to Black, but without reaching their slowness.
  • "All Nightmare Long" is just plain awesome. I love that chorus of "Hunt you down without mercy"
  • "My Apocalypse" is an awesome way to end the album. It's fast and lots of violent, death imagery without the cartooniness rampant in today's "modern" heavy metal.


The world could have done without "The Unforgiven III", which is the only clunker on the album. Overall, it's a massive step in the right direction for the band -- their last few studio works had more clunkers than gems. I think it fits firmly into the sort of work they should have put out following ...And Justice for All and/or Metallica.

Overall, I have to give this one 4 out of 5 stars. It's no Master of Puppets, but it's definitely more in line with what the Metallica fan base was looking for.

(Yes, I know that I whored this review up with Amazon links. Hey, guy's gotta eat, you know.)

Friday, September 12, 2008

Chapter Two excerpt



Support independent publishing: buy this book on Lulu.


The second chapter from the urban fantasy novel The Path Into Darkness is available here (pdf is here).

Thursday, September 11, 2008

Now if only I had a Kindle....





The Kindle Edition of The Path Into Darkness is available on Amazon.com.

Of course, I didn't plan ahead in any fashion and actually buy a Kindle, so I can see what it looks like or anything on the final platform. Noooo, that would've made sense.

Wednesday, September 10, 2008

Another day, another page

I've been very slowly (very very very slowly) working on my next novel-length story. I'm trying something different this time, in both genre and in my approach to the actual writing.

Approach-wise, I'm trying to do more up-front planning, including a plot synopsis, somewhat detailed character sketches (that can change, of course, if the story requires). I usually don't plan these things out and just use the BIC approach (but-in-chair), but that hasn't been working at all for this project -- this approach makes me what some call a "pantser" (due to writing by the seat of one's pants). It feels that I need to have some structure in place to cajole the characters into starting along with their plots and motives.

Genre-wise, it's more of a science-fiction work than I usually do (I usually write some sort of fantasy, most often ye olde "high fantasy"). This one has a more dystopian setup, with evil/ruthless drug companies, disaffected youth, etc. It's a stretch for me, but I like the idea too much to just disregard it.

Anyway, I'm about 9 pages in on the rough draft, and I like what I've written so far, which is also a first because I usually don't like what's on the page until somewhere in the mid-20s.

Monday, September 8, 2008

Chapter One excerpt



Support independent publishing: buy this book on Lulu.


The first chapter from the urban fantasy novel The Path Into Darkness is available here (pdf is here).

Saturday, September 6, 2008

New Site Launch



Support independent publishing: buy this book on Lulu.


Launched a new site to sort of centralize information about the book The Path Into Darkness. There's not much content there yet, mostly because the book is still winding it's way through the distributor channels before it can get listed and sold on online bookstores, although it is available at the author's storefront.

Next week, excerpts from the book will be available.

Friday, September 5, 2008

Adventures in Webpage Content Injection.

I run several web sites and recently decided that I wanted to add some common text to the bottom of all the pages. Since I don't generate the content, it would be best if the server did this as it served the pages.

A quick search through Apache's module directory and I saw that mod_layout fit the bill ... in theory, at least. I had tried, in vain, for the last two days to get mod_layout working with my antiquated Linux server (fedora core 3), before I decided that I should really look into my other options -- especially since mod_layout hadn't been updated and from what I could see from forums, it's developer wasn't exactly interested in making it working with Apache 2.0+.

Then I saw a post about how mod_rewrite could be cajoled into doing this sort of a task. Essentially it does this by rewriting the request into a CGI call, passing the original requested file name as a paramter.

Like so:


RewriteRule /(.*) /wrapper.cgi?file=$1 [nc,l,qsa]


All the examples were using PHP. My server is old (as mentioned above) and you can't really find RPM's for older Fedora's. So, since I don't have PHP installed, I looked at my options ... and it immediately struck me that Python would be up to the task.

So, you need to create a Python scripted named
wrapper.cgi
which contains:

import os
import os
import re
import urllib

print "Content-type: text/html"
print
docroot = os.getenv( 'DOCUMENT_ROOT' )
fname = docroot + urllib.unquote( os.getenv( 'REQUEST_URI' ) )
buff = open( fname ).read( )

mobj = re.compile( '<body[^>]*>', re.IGNORECASE | re.VERBOSE )
mobj2 = re.compile( '</body>', re.IGNORECASE | re.VERBOSE )
obj = mobj.search( buff )
obj2 = mobj2.search( buff )
header = buff[:obj.end()]
body = buff[obj.start( ):obj2.start( )]
footer = buff[obj2.start():]

print header
if os.path.exists( docroot + '/header.inc' ):
print open( docroot + '/header.inc' ).read( )
print body
if os.path.exists( docroot + '/footer.inc' ):
print open( docroot + '/footer.inc' ).read( )
print footer


So, now I have a framework and method for wrapping all the assorted web pages with some common header & footer code (such as some essential support links, for example).

Thursday, September 4, 2008

Rider-Waite tarot card images

Hmm...just noticed that the images used on Wikipedia are from the original deck, which is in the public domain. Which is useful, since I want to use them as part of a book cover, and now I don't have to pay royalties or seek permissions.

Happy day.

Wednesday, September 3, 2008

Plone and the annoying ATAmazon...

So, I recently tried to make more use out of my Amazon Associate Id that I had gotten way back in 2001. Since I run Plone on a few of my sites, I tried to to install the ATAmazon product.

It didn't work.

Not only didn't it work, but it didn't even give me very helpful error messages to try to fix the problem myself. Other people seem to use it ... or at least know about it. I enter in the proper ASIN number (I know this, because you can click on the "Buy" button that it shows and go to the proper item's page), but none of the details seem to either retrieved or parsed properly.

Any tips or clues to help resolve this would be most welcome.

(EDIT: Silly amazon "deprecated" that version of their web services. Unlike the usual method of deprecation, they simply turned it off!)

Monday, September 1, 2008

Stackless Python meets Twisted Matrix....




Sometimes, you come across two programming toolkits that would go great together. However, in the case of Twisted Matrix and Stackless python, there's some legwork required to get these two great systems to work together.
Twisted requires that it's reactor runs in the main "tasklet", but if there is no network activity or other deferred code to execute, the reactor loop will stop the entire application and thus defeat the purpose behind using tasklets and Stackless.

There is some setup required to get this all working together.

import stackless
from twisted.internet import reactor, task
reactor_tasklet = None

def reactor_run( ):
reactor_tasklet = stackless.getcurrent( )
# repeatedly call stackless.schedule every 0.0001 seconds
schedulingTask = task.LoopingCall( stackless.schedule )
# this prevents the reactor from blocking out the other tasklets
schedulingTask.start( 0.0001 )
reactor.run( )

t = stackless.tasklet( reactor_run )
t.run( )
# run the stackless scheduler.
stackless.run( )

Now, extending out this simple case to a more general solution involves the use of Python's function decorators. (I use the great decorator.py module to make decorators a little easier to write.)
def __filter( d ):
if isinstance( d, failure.Failure ):
if isinstance( d.value, TaskletExit ):
print "ignore taskletexit"
return None
return d
return d

def __wrapper( d, f, *args, **kwargs ):
try:
rv = defer.maybeDeferred( f, *args, **kwargs )
rv.addCallback( __filter )
rv.addCallback( d.callback )
rv.addErrback( __filter )
except TaskletExit:
pass
except Exception, e:
print e, dir( e )
d.errback( e )


Above is just some boiler-plate code. __filter screens out the TaskletExit exception that gets sent to Tasklets; if this isn't done, the Twisted framework wraps it up in an instance of twisted.python.failure.Failure and you get "Unhandled error in Deferred" exceptions at the calling point. Since this is almost never what you want, it's easiest to just filter it out. Of course, in real code you'll remove the line reading 'print "ignore taskletexit"'.

__wrapper does the actual heavy lifting of the function call. It uses the maybeDeferred function to ensure that after the function call we are only dealing with Deferred's. __wrapper uses Twisted's usual callback mechanism to ensure that the Deferred that it received as a function paramater is called once the results of the actual function call is available. This parameter Deferred is essential for the function decorators described next to work.

reactor_tasklet = None

@decorator
def deferred_tasklet( f, *args, **kwargs ):
d = defer.Deferred( )
t = stackless.tasklet( __wrapper )
t( d, f, *args, **kwargs )
t.run( )
return d


@decorator
def blocking_tasklet( f, *args, **kwargs ):
f2 = deferred_tasklet( f )
d = f2( *args, **kwargs )
if reactor_tasklet != stackless.getcurrent( )
and stackless.getcurrent( ) != stackless.getmain( ):
return block_on( d )
raise RuntimeError( "Cannot block in reactor task" )


def block_on( d ):
chan = stackless.channel( )
d.addBoth( lambda x,y=chan: y.send( x ) )
return chan.receive( )

Here we have the two main function decorators deferred_tasklet and blocking_tasklet, as well as the utiliity function block_on. The first of these simply returns a Deferred, suspiciously the very same Deferred that it passes as a parameter to the __wrapper function; which, if you've been paying attention, will be triggered once the results of the wrapped-up function are available. All we're really doing here is creating a stackless.tasklet and running __wrapper in that new microthread.

blocking_tasklet goes one step beyond this, and takes the Deferred that we were passed earlier and converts it into a blocking function call. First, it does some sanity checks to ensure that it's not blocking in the same tasklet that Twisted's reactor is running in. Somewhere you need to store the value of stackless.getcurrent() when called from with the reactor's tasklet. We also need to make sure that our current tasklet is not the "main" Stackless tasklet; this should never happen, but I like to be safe at times.

The utility function block_on sets up a Stackless channel. It then adds a simple little lambda closure. This closure only send's it's parameter to the stackless channel. This closure is added to both the callback and errback chain of the Deferred that we're going to wait on. After this is all set up, we then call receive, which blocks this tasklet until the Deferred is finished and the callbacks/errback is fired off. At this point, we receive the return value of the original function through the channel and can return it as the return value of our function.

As long as we are not in the same tasklet as Twisted's reactor, we can use this block_on function to turn our other wise asynchronous code into a sequentially execute synchronous code. This can also be done using Twisted's inlineCallbacks decorator, but that turns the decorated function into a generator, which isn't always what we want.