From mpfaiffer at callapple.org  Sun Apr  2 16:46:31 2006
From: mpfaiffer at callapple.org (Mike Pfaiffer)
Date: Sun, 02 Apr 2006 15:46:31 -0500
Subject: [Python Wpg] Finally got the program up on the web
Message-ID: <200604021546.31251.mpfaiffer@callapple.org>

 Bear in mind this is version 1.0 and it's intended to show that Python 
actually works. Since I'll demo the program at the next meeting we can talk 
about improvements then (Yes I deliberately programmed it badly so I can get 
another article and a presentation or two out of writing improvements and 
style changes - That's my story and I'm sticking to it).

 Here is the URL. Download and enjoy. :-)

http://members.shaw.ca/digitalcivilization/samples.html

    Later
    Mike

-- 
+----------------------------------------------------------------------+
|Call-A.P.P.L.E. and the Digital Civilization http://www.callapple.org |
|   http://members.shaw.ca/pfaiffer = Mike Pfaiffer (B.A., B.Sc.)      |
+----------------------------------------------------------------------+
----- BEGIN GEEK CODE BLOCK -----
Version: 3.12
GCS/G/IT/PA/SS d s+:- a? C++ UL L++ W++ N++ o+ K- w(---) O+@ M++@ V PS+
PE !PGP t+ 5+ X R tv b+ DI+++ D++ G e++* h! r-- !y-- UF++
------ END GEEK CODE BLOCK ------


From syd at plug.ca  Mon Apr  3 00:53:04 2006
From: syd at plug.ca (Sydney Weidman)
Date: Sun, 02 Apr 2006 23:53:04 -0500
Subject: [Python Wpg] Howto on Plone.org
Message-ID: <1144039984.12098.18.camel@localhost.localdomain>

I just got my first howto published on plone.org! You can read it at:

http://plone.org/documentation/how-to/quickie-plone-backup-using-repozo

It wasn't much, but I had fun doing it, and the plone community needs
documentation :-)

Also, I discovered that if you assign command line arguments to
sys.argv[1:], then import a script that uses command line arguments, the
arguments you assigned will be passed to the imported script. See the
backup-zope.py script that I included with the howto.

Regards,
Syd

-- 
Sydney Weidman <syd at plug.ca>
Prairie Linux User Group


From stuartw at mts.net  Wed Apr 12 15:32:43 2006
From: stuartw at mts.net (Stuart Williams)
Date: Wed, 12 Apr 2006 14:32:43 -0500
Subject: [Python Wpg] April meeting, web site
Message-ID: <17469.21979.787369.766895@gargle.gargle.HOWL>

The location for the April 26th meeting has been set, to the same room
as last month.  After that it moves to a different room at the UW.
The room number and directions are on the wiki at http://WinniPUG.ca.

Note that URL redirects to our python.org wiki page, so you can use it
to direct to the page about us when you're telling all your friends
and associates and people on the street about the users group.  Take a
few minutes to think about people that might want to attend and drop
them a line.

Stuart.


From sbalneav at legalaid.mb.ca  Wed Apr 12 16:17:45 2006
From: sbalneav at legalaid.mb.ca (Scott Balneaves)
Date: Wed, 12 Apr 2006 15:17:45 -0500
Subject: [Python Wpg] Python newbie!
Message-ID: <20060412201745.GC30812@localdomain>

Hello to all!

After receiving a gracious invitation from Stuart to join, here I am.

I'm fairly new to Python, having only spent about 3 or 4 months
semi-activly dabbling with it.  I've got the following books already:

Learning Python         -\
Python Cookbook           \
Programming Python         >---  O'Really?
The Twisted Framework     /
Python In A Nutshell    -/

Python Network Programming (some lesser book company)

Learning anything's always an excuse to buy more books, right?

My immediate question is the following:

#@+others
#@+node:imports

I think this is called "decoration", but I've yet to find an
understandable (to me, anyway) explaination as to what they are.

Help a poor (hopefully ex in a while) C programmer out with a clue?

Scott

-- 
Scott L. Balneaves | "Looking beyond the embers of bridges glowing behind us
Systems Department |  To a glimpse of how green it was on the other side..."
Legal Aid Manitoba |    -- Pink Floyd "High Hopes"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060412/e0acc112/attachment.sig>

From stuartw at mts.net  Wed Apr 12 17:57:51 2006
From: stuartw at mts.net (Stuart Williams)
Date: Wed, 12 Apr 2006 16:57:51 -0500
Subject: [Python Wpg] Python newbie!
In-Reply-To: <20060412201745.GC30812@localdomain>
References: <20060412201745.GC30812@localdomain>
Message-ID: <17469.30687.371688.317020@gargle.gargle.HOWL>

>>>>> Scott Balneaves writes:
> Subject: [Python Wpg] Python newbie!

> My immediate question is the following:

> #@+others
> #@+node:imports

> I think this is called "decoration", but I've yet to find an
> understandable (to me, anyway) explaination as to what they are.

While the '@' is used for Python decorators, these are just comments
as far as Python is concerned, because they appear after hash marks.

I believe those are commands for the editor Leo.

Stuart.


From mpfaiffer at callapple.org  Wed Apr 12 19:59:48 2006
From: mpfaiffer at callapple.org (Mike Pfaiffer)
Date: Wed, 12 Apr 2006 18:59:48 -0500
Subject: [Python Wpg] Python newbie!
In-Reply-To: <20060412201745.GC30812@localdomain>
References: <20060412201745.GC30812@localdomain>
Message-ID: <200604121859.48752.mpfaiffer@callapple.org>

On April 12, 2006 03:17 pm, Scott Balneaves wrote this amazing epistle:
> Hello to all!
>
> After receiving a gracious invitation from Stuart to join, here I am.
>
> I'm fairly new to Python, having only spent about 3 or 4 months
> semi-activly dabbling with it.  I've got the following books already:

 About the same amount of time I have. I have no books. I just read the 
documentation on the python.org site. The more ask and read the more I find 
out about the language. Since I run a variety of platforms it is easier to 
port source from one machine to another than say... C, Pascal, JAVA. I'll be 
doing quite a bit of that in a couple of months.

> Learning Python         -\
> Python Cookbook           \
> Programming Python         >---  O'Really?
> The Twisted Framework     /
> Python In A Nutshell    -/

 Anything for a "leg up". ;-)

> Python Network Programming (some lesser book company)

 Let me know if you get a newer version. I'd be interested in picking this one 
up from you.

> Learning anything's always an excuse to buy more books, right?

 Naturally.

> My immediate question is the following:
>
> #@+others
> #@+node:imports
>
> I think this is called "decoration", but I've yet to find an
> understandable (to me, anyway) explaination as to what they are.
>
> Help a poor (hopefully ex in a while) C programmer out with a clue?

 Scott... You have my respect for finding things which are very much out of 
the ordinary. You are very much a "geeks geek". I salute you. I can only 
dream of the lofty heights of "nerd-dom" you have achieved. You're pretty 
smart too... ;-) As someone writing their first Python program I'll have to 
defer to Stuart on this one. At the same time I am reminded of compiler 
directives in Turbo Pascal. They were placed within "{}" comments. Would your 
source hint at something similar?

> Scott

 BTW, good presentation last night. I got and installed FUSE as well as sshfs. 
It complained when I ran it (Fedora 2.0). I'll follow up in the MUUG mailing 
list in a couple of days. I want to try a couple more things to get it 
working first (like more reading of the install section a little earlier in 
the day than 1:30am). ;-)

-- 
+----------------------------------------------------------------------+
|Call-A.P.P.L.E. and the Digital Civilization http://www.callapple.org |
|   http://members.shaw.ca/pfaiffer = Mike Pfaiffer (B.A., B.Sc.)      |
+----------------------------------------------------------------------+
----- BEGIN GEEK CODE BLOCK -----
Version: 3.12
GCS/G/IT/PA/SS d s+:- a? C++ UL L++ W++ N++ o+ K- w(---) O+@ M++@ V PS+
PE !PGP t+ 5+ X R tv b+ DI+++ D++ G e++* h! r-- !y-- UF++
------ END GEEK CODE BLOCK ------


From sbalneav at legalaid.mb.ca  Thu Apr 13 16:32:34 2006
From: sbalneav at legalaid.mb.ca (Scott Balneaves)
Date: Thu, 13 Apr 2006 15:32:34 -0500
Subject: [Python Wpg] LdapFS initial spec
Message-ID: <20060413203234.GA3826@localdomain>

Hello Stuart, and others:

Well, I did have other stuff to do, but after our lunch, I was too
geeked up to do "boring" work, and instead, wrote down an initial spec
for LdapFS, a python + fuse + ldap filesystem that Stuart proposed
working on together.  Here's the text of the spec, and (for prettier
formatting), an ODT document.

Cheers!

To:     Stuart Williams, WinniPUG
From:   Scott Balneaves
Date:   April 13, 2006
Re:     LdapFS spec


Introduction:

LdapFS will be a FUSE based file system written in Python.  It's
function to be providing access to an LDAP based directory tree via
standard file system semantics.

Scope:

For the initial release, LdapFS should focus on a top-down tree.  The
base Distinguished Name that is passed to the LdapFS should be made
available in some manner to the program, and the file system should be
read/write for a privileged user, and read-only otherwise.  The various
OU's of the tree will be the base of the mount point.  A fully qualified
DN will be the last level of directory.  Within that directory, the
various attributes will appear to be files, with the attribute name
being the name of the file.  The value of the attribute will be the
contents of the file.  Creating a new file (if one has privilege to do
so) will create a new attribute, with the value of the attribute set to
the contents of the file.  Removing a file will, of course, delete the
attribute, and deleting the directory will, naturally remove that DN
from the LDAP database.   This leads to the horrific possibility of
wiping out the entire corporate LDAP database with a stray rm -rf *,
however the price of systems administration is eternal vigilance.  The
interesting possibility of backup and restore of the LDAP database using
tar becomes possible too.

Implementation:

  * The FUSE base LdapFS file system will be written in Python for maximum
    portability.  The LdapFS file system will be multi-threaded for
    performance. 
  * The Base Distinguished Name (BDN) and server address could be passed in
    on the command line, either via two separate switches (-s & -dn), or via
    a URL (ldap://server/dn...).   The login password and userid for the
    LDAP database should probably either have to be stored in a
    root-only-readable file (/etc/ldapfs.conf), or perhaps better, both
    could be gotten by parsing the ldap config files (/etc/ldap/ldap.conf
    and /etc/ldap.secret on Debian/Ubuntu).
  * By default The mount point for the file system is also passed on the
    command line, per standard FUSE semantics, as well as any fuse specific
    command line options.
  * Files within the file system should probably appear to be owned by root,
    and group owned by ldap, and chmod 664.  That way, root and users within
    the ldap group would have read/write access, and other users would have
    read access only.
  * Most attribute/value pairs within LDAP don't have a trailing '\n',
    however, for readability purposes, one should be added when a fuse read
    option is used, and when a value is written, the trailing '\n' will have
    to be stripped off before being stored in the LDAP database.
  * It is unknown at this point if it would be better to use the ldap, or
    the curl library for connection via Python.  This should be investigated
    further to determine which would be the best fit for read/write access
    to an LDAP database.

Use Cases:

John Smallberries is a systems administrator at YoYoDyne industries.
His Base DN for his LDAP tree is dc=yoyodyne,dc=com.  He needs to change
the gecos field for  userid jbigboot from John Bigbootie to John
Bigbootay.  His LDAP server has 3 Organizational Units (OU's), namely
users, groups, and aliases.

After mounting the LdapFS file system on /ldap, he cd's into /ldap, and
sees three directories:

aliases/   groups/   users/

He cd's into users, and does an ls, and sees the users for OU=users:

drlizard/  jbigboot/  jsmallbe/  jyayas/

He cd's into jbigboot/, which corresponds to the DN
uid=jbigboot,ou=users,dc=yoyodyne,dc=com, and sees the following files
(not in order, I'm too lazy):

uid  objectClass  userid  description  seeAlso  ...  gecos

He cat's the gecos file, which returns:

John Bigbootie

John Smallberries has found what he needs, and fixes the problems with:

echo John Bigbootay > gecos

Problems likely to be encountered:

Editing a file, as opposed to rewriting it may cause problems, as we'll
somehow have to handle writing substrings at offsets, as opposed to
simply re-writing the whole attribute.  It will be something to keep in
mind during implementation.

Scott Balneaves

-- 
Scott L. Balneaves | "Looking beyond the embers of bridges glowing behind us
Systems Department |  To a glimpse of how green it was on the other side..."
Legal Aid Manitoba |    -- Pink Floyd "High Hopes"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LdapFSspec.odt
Type: application/vnd.oasis.opendocument.text
Size: 19314 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060413/863960be/attachment.odt>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060413/863960be/attachment.sig>

From sbalneav at legalaid.mb.ca  Fri Apr 14 03:15:13 2006
From: sbalneav at legalaid.mb.ca (Scott Balneaves)
Date: Fri, 14 Apr 2006 02:15:13 -0500
Subject: [Python Wpg] It's 2:10 AM, do you know where LdapFS is?
Message-ID: <20060414071513.GA11758@localdomain>

Man, I need to get a life.

#!/usr/bin/python

#
# Fools rush in...
#

from fuse import Fuse
from errno import *
from stat import *
import ldap

class LdapFS(Fuse):

    def __init__(self, *args, **kw):
    
        Fuse.__init__(self, *args, **kw)

        # 
        # Open our LDAP connection for use later.
        #

        self.path   = 'dc=legalaid,dc=mb,dc=ca'
        self.host   = 'localhost'
        self.passwd = 'oogabooga'
        
        try:
            self.ldap_handle = ldap.open(self.host);
            self.ldap_handle.simple_bind('cn=ldapadmin,' + self.path, \
                                         self.passwd)
        except ldap.LDAPError, error:
            print 'Problem with ldap:', error

    def getattr(self, path):
        """
        Ick.  So broken it's not even funny.
        """
        mode =
S_IFDIR|S_IRUSR|S_IXUSR|S_IWUSR|S_IRGRP|S_IXGRP|S_IXOTH|S_IROTH
        ino  = 1
        dev  = 8193L
        link = 2
        uid  = 0
        gid  = 0
        size = 4096L
        atime = 0
        mtime = 0
        ctime = 0
        
        return (mode, ino, dev, link, uid, gid, size, atime, mtime,
ctime)

    def getdir(self, path):
        mydir = [('.', 0), ('..', 0)]
        try:
            result = self.ldap_handle.search_s(self.path, \
                                               ldap.SCOPE_SUBTREE,
'(ou=*)')
        except ldap.LDAPError, error:
            print 'Problem with ldap:', error

        ous = []
        for ou in result:
            ous.append(ou[0])
            
        mydir.extend(map(lambda x: (x,0), ous))
        return mydir

if __name__ == '__main__':

        server = LdapFS()
        server.multithreaded = 1;
        server.main()


-------

sbalneav at phobos:~$ ./LdapFS.py ~/foo

(in another window)

sbalneav at phobos:~$ ls -la ~/foo
total 24
drwxr-xr-x   2 root     root     4096 Dec 31  1969 .
drwxr-xr-x  89 sbalneav sbalneav 8192 Apr 14 01:05 ..
drwxr-xr-x   2 root     root     4096 Dec 31  1969 ou=groups,dc=legalaid,dc=mb,dc=ca
drwxr-xr-x   2 root     root     4096 Dec 31  1969 ou=phpgwgroups,dc=legalaid,dc=mb,dc=ca
drwxr-xr-x   2 root     root     4096 Dec 31  1969 ou=users,dc=legalaid,dc=mb,dc=ca
sbalneav at phobos:~$ fusermount -u ~/foo

Well, it's something.

Scott

-- 
Scott L. Balneaves | "Looking beyond the embers of bridges glowing behind us
Systems Department |  To a glimpse of how green it was on the other side..."
Legal Aid Manitoba |    -- Pink Floyd "High Hopes"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060414/6d76e9c8/attachment.sig>

From sbalneav at legalaid.mb.ca  Sun Apr 16 22:47:38 2006
From: sbalneav at legalaid.mb.ca (Scott Balneaves)
Date: Sun, 16 Apr 2006 21:47:38 -0500
Subject: [Python Wpg] LdapFS.py moving along, navigation not complete,
	but semi functional.
Message-ID: <20060417024738.GB13115@localdomain>

Hello Stuart et al:

Well, after some twiddling over the last couple of days, and some
advice from my buddy Ivan Krstic, I've not only got something that
works, but is (hopefully) conformant to PEP8.  So yay for me!

For other interested parties looking to play along with the home game,
I've attached some other files as well.

Installing an ldap server's pretty easy.  aptitude install slapd works
on superior distros, "other" distros I'm not sure about.

After you've got it installed, you should have the utility "slapadd".
The ldap.conf and slapd.conf file I've included can be used as a base to
fix up your own files included in /etc/ldap/...  After you've got things
modified, bud before you do a invoke-rc.d slapd start, running 
slapadd -l yoyodyne.ldif should create a "sample" ldap database.  If
you've already GOT one, don't do any of that. :)

LdapFS.py can be invoked, as a regular user, by:

./LdapFS.py ~/somedir

where somedir is somedir in your homedir.

Next on the hitlist: Reading, so I can do things like cat cn.  Should be
cool.

I'll be away next week, but I'll me monitoring my email, and should be
working on it a bit anyway.  

Cheers,
Scott

-- 
Scott L. Balneaves | "Looking beyond the embers of bridges glowing behind us
Systems Department |  To a glimpse of how green it was on the other side..."
Legal Aid Manitoba |    -- Pink Floyd "High Hopes"
-------------- next part --------------
dn: dc=yoyodyne,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Yoyodyne Propulsion Systems
dc: yoyodyne
structuralObjectClass: organization

dn: cn=admin,dc=yoyodyne,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
structuralObjectClass: organizationalRole
userPassword: oogabooga

dn: ou=users,dc=yoyodyne,dc=com
objectClass: organizationalUnit
objectClass: top
description: Yoyodyne Users
ou: users
structuralObjectClass: organizationalUnit

dn: uid=drlizard,ou=users,dc=yoyodyne,dc=com
uid: drlizard
description: Dr. Emelio Lizardo
host: lectroid
cn: Emelio Lizardo
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/drlizard
loginShell: /bin/bash
gecos: Emelio Lizardo
shadowWarning: 7
structuralObjectClass: account
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowMax: 180
userPassword:: e1NTSEF9Uldpcnp4RncwU2dnYzgrZXk2dzBEd29zN0xVVDd5STU=
shadowLastChange: 13207

dn: uid=jbigboot,ou=users,dc=yoyodyne,dc=com
uid: jbigboot
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowWarning: 7
uidNumber: 1001
gidNumber: 1000
homeDirectory: /home/jbigboot
loginShell: /bin/bash
structuralObjectClass: account
shadowMax: 180
cn: John Bigbootie
userPassword:: e1NTSEF9d1gzZGx6eEZIUTRKeFZhWjVTcmcyWktLNmRRNmVaS1o=
shadowLastChange: 13202

dn: uid=jsmallbe,ou=users,dc=yoyodyne,dc=com
shadowWarning: 7
uidNumber: 1002
gidNumber: 1000
homeDirectory: /home/jsmallbe
loginShell: /bin/bash
structuralObjectClass: account
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowMax: 180
userPassword:: e1NTSEF9bm5xWXFGLzJxRi85MTNxOEdHdXN2dUxacGtTREhEcU4=
shadowLastChange: 13116
uid: jsmallbe
cn: John Smallberries

dn: uid=jmanyjar,ou=users,dc=yoyodyne,dc=com
uid: jmanyjar
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowWarning: 7
uidNumber: 1003
gidNumber: 1000
homeDirectory: /home/jmanyjar
loginShell: /bin/bash
structuralObjectClass: account
shadowMax: 180
userPassword:: e1NTSEF9UmlzOUplalVaTURFTi90eWpmS3lYRHNpUVV4Mi9STEs=
shadowLastChange: 13122
cn: John Many Jars

dn: ou=groups,dc=yoyodyne,dc=com
objectClass: organizationalUnit
objectClass: top
ou: groups
description: Yoyodyne Groups
structuralObjectClass: organizationalUnit

dn: cn=research,ou=groups,dc=yoyodyne,dc=com
objectClass: posixGroup
objectClass: top
cn: research
gidNumber: 1000
memberUid: drlizard
memberUid: jbigboot
memberUid: jsmallbe
memberUid: jmanyjar
structuralObjectClass: posixGroup

dn: cn=executive,ou=groups,dc=yoyodyne,dc=com
objectClass: posixGroup
objectClass: top
cn: executive
gidNumber: 1001
memberUid: drlizard
structuralObjectClass: posixGroup
-------------- next part --------------
BASE	dc=yoyodyne,dc=com
URI	ldap://localhost

#SIZELIMIT	12
#TIMELIMIT	15
#DEREF		never
-------------- next part --------------
allow bind_v2
include         	/etc/ldap/schema/core.schema
include         	/etc/ldap/schema/cosine.schema
include         	/etc/ldap/schema/nis.schema
include         	/etc/ldap/schema/inetorgperson.schema
schemacheck     	on
pidfile         	/var/run/slapd/slapd.pid
replica-pidfile 	/var/run/slurpd/slurpd.pid
argsfile        	/var/run/slapd.args
replica-argsfile 	/var/run/slurpd.args
loglevel        	0
modulepath      	/usr/lib/ldap
moduleload       	back_bdb
password-hash 		{SSHA}
defaultsearchbase	"dc=yoyodyne,dc=com"
backend         	bdb
database        	bdb
suffix          	"dc=yoyodyne,dc=com"
directory       	"/var/lib/ldap"
index           	objectClass,uid,uidNumber,gidNumber eq
index           	cn,mail,surname,givenName  eq,subinitial
lastmod         	on
replogfile      	/var/lib/ldap/replog
rootdn 			"cn=admin,dc=yoyodyne,dc=com"
rootpw 			"oogabooga"
access to *
       by dn.regex="cn=admin,dc=yoyodyne,dc=com" write
       by * read
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LdapFS.py
Type: text/x-python
Size: 3215 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060416/20f6f1e6/attachment.py>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060416/20f6f1e6/attachment.sig>

From stuartw at mts.net  Mon Apr 17 15:57:04 2006
From: stuartw at mts.net (Stuart Williams)
Date: Mon, 17 Apr 2006 14:57:04 -0500
Subject: [Python Wpg] Python advocacy in Winnipeg
Message-ID: <17475.62224.283024.968389@gargle.gargle.HOWL>

I have made some informal offers to local businesses in IT to give a
presentation on Python to their IT staff.  There's also a possibility
that I'll teach a Python class in Winnipeg in the next while.

I added the following to the wiki:
 
  Do you want to find out more about Python from a demo, a tutorial,
  or a class? Do you have other questions about this group? Contact
  Stuart Williams

This raises a few questions.

Does anyone object to my publicly naming myself one of official
contacts for this group?

Are there others who would be interested in giving presentations to
groups outside our group?

My contact information on the wiki could generate contract work for
me.  Are there others who would like to be listed?  Should we add a
section to the wiki page listing Winnipeg area Python contractors and
consultants?

Stuart.


From syd at plug.ca  Mon Apr 17 16:28:02 2006
From: syd at plug.ca (syd at plug.ca)
Date: Mon, 17 Apr 2006 15:28:02 -0500 (CDT)
Subject: [Python Wpg] Python advocacy in Winnipeg
In-Reply-To: <17475.62224.283024.968389@gargle.gargle.HOWL>
References: <17475.62224.283024.968389@gargle.gargle.HOWL>
Message-ID: <63399.142.132.4.215.1145305682.squirrel@mail2.plug.ca>

> I have made some informal offers to local businesses in IT to give a
> presentation on Python to their IT staff.  There's also a possibility
> that I'll teach a Python class in Winnipeg in the next while.
>
> I added the following to the wiki:
>
>   Do you want to find out more about Python from a demo, a tutorial,
>   or a class? Do you have other questions about this group? Contact
>   Stuart Williams
>
> This raises a few questions.
>
> Does anyone object to my publicly naming myself one of official
> contacts for this group?
>

I have no objections. If others would like to list themselves, it might be
good to have a section with categories like courses/consultants/jobboard
etc.

Regards,
Syd



From mpfaiffer at callapple.org  Mon Apr 17 16:28:49 2006
From: mpfaiffer at callapple.org (Mike Pfaiffer)
Date: Mon, 17 Apr 2006 15:28:49 -0500
Subject: [Python Wpg] Python advocacy in Winnipeg
In-Reply-To: <17475.62224.283024.968389@gargle.gargle.HOWL>
References: <17475.62224.283024.968389@gargle.gargle.HOWL>
Message-ID: <200604171528.49076.mpfaiffer@callapple.org>

On April 17, 2006 02:57 pm, Stuart Williams wrote this amazing epistle:
> I have made some informal offers to local businesses in IT to give a
> presentation on Python to their IT staff.  There's also a possibility
> that I'll teach a Python class in Winnipeg in the next while.
>
> I added the following to the wiki:
>
>   Do you want to find out more about Python from a demo, a tutorial,
>   or a class? Do you have other questions about this group? Contact
>   Stuart Williams
>
> This raises a few questions.
>
> Does anyone object to my publicly naming myself one of official
> contacts for this group?

 I have no problem. If anybody wants to step up to volunteer as an additional 
contact then they should be listed too.

> Are there others who would be interested in giving presentations to
> groups outside our group?

 I have no problems giving presentations in general. I'd need more experience 
with the language in order to give a specific presentation.

> My contact information on the wiki could generate contract work for
> me.  Are there others who would like to be listed?  Should we add a
> section to the wiki page listing Winnipeg area Python contractors and
> consultants?

 If someone wants to list me as a junior, part time programmer learning Python 
I would not object. OTOH, a link to callapple.org (where I write articles) 
might be something else entirely.

> Stuart.
> _______________________________________________
> Winnipeg mailing list
> Winnipeg at python.org
> http://mail.python.org/mailman/listinfo/winnipeg

    Later
    Mike



-- 
+----------------------------------------------------------------------+
|Call-A.P.P.L.E. and the Digital Civilization http://www.callapple.org |
|   http://members.shaw.ca/pfaiffer = Mike Pfaiffer (B.A., B.Sc.)      |
+----------------------------------------------------------------------+
----- BEGIN GEEK CODE BLOCK -----
Version: 3.12
GCS/G/IT/PA/SS d s+:- a? C++ UL L++ W++ N++ o+ K- w(---) O+@ M++@ V PS+
PE !PGP t+ 5+ X R tv b+ DI+++ D++ G e++* h! r-- !y-- UF++
------ END GEEK CODE BLOCK ------


From billreid at shaw.ca  Mon Apr 17 16:31:03 2006
From: billreid at shaw.ca (Bill Reid)
Date: Mon, 17 Apr 2006 15:31:03 -0500
Subject: [Python Wpg] Python advocacy in Winnipeg
In-Reply-To: <17475.62224.283024.968389@gargle.gargle.HOWL>
References: <17475.62224.283024.968389@gargle.gargle.HOWL>
Message-ID: <4443FB07.8050100@shaw.ca>

Stuart Williams wrote:

> Does anyone object to my publicly naming myself one of official
> contacts for this group?
> 

Fine with me.

-- Bill



From jason at peaceworks.ca  Mon Apr 17 16:51:46 2006
From: jason at peaceworks.ca (Jason Hildebrand)
Date: Mon, 17 Apr 2006 15:51:46 -0500
Subject: [Python Wpg] Python advocacy in Winnipeg
In-Reply-To: <17475.62224.283024.968389@gargle.gargle.HOWL>
References: <17475.62224.283024.968389@gargle.gargle.HOWL>
Message-ID: <1145307106.27285.159.camel@trotzdem.wpg.peaceworks.ca>

On Mon, 2006-04-17 at 14:57 -0500, Stuart Williams wrote:
> Does anyone object to my publicly naming myself one of official
> contacts for this group?

Not at all.

> My contact information on the wiki could generate contract work for
> me.  Are there others who would like to be listed?  Should we add a
> section to the wiki page listing Winnipeg area Python contractors and
> consultants?

Adding a list of contractors/consultants makes sense to me.  I might be
interested in being listed in the future.

-- 
Jason D. Hildebrand
T: 204 775 1212
E: jason at peaceworks.ca




From stuartw at mts.net  Tue Apr 18 12:49:46 2006
From: stuartw at mts.net (Stuart Williams)
Date: Tue, 18 Apr 2006 11:49:46 -0500
Subject: [Python Wpg] LdapFS.py moving along, navigation not complete,
	but semi functional.
In-Reply-To: <20060417024738.GB13115@localdomain>
References: <20060417024738.GB13115@localdomain>
Message-ID: <17477.6314.467103.142572@gargle.gargle.HOWL>

>>>>> Scott Balneaves writes:

> Next on the hitlist: Reading, so I can do things like cat cn.  Should be
> cool.

Scott or others,

The following works, but it's returning length = 4096 characters
instead of the length of the attribute.  The code in _fusemodule.c
appears to handle setting the length correctly from the string
returned from the read function.  Any ideas?

    def read(self, path, length, offset):
        print "ldapfs:read:read(%s, %d, %d)" % (path, length, offset)
        if length == 0:
            return ""

        pl = path.split('/')
        assert pl[0] == ''             # should have split on leading /
        rdns = pl[1:-1]
        rdns.reverse()
        attr =  pl[-1]
        search_dn = ','.join(rdns + [self.basedn])
        result = self.conn.search_s(search_dn,
                                    ldap.SCOPE_SUBTREE,
                                    '(objectClass=*)', [attr])
        attr_val = result[0][1][attr][0]
        print type(attr_val)
        print attr_val
        print len(attr_val)
        return attr_val[offset:offset+length]
    


From brent at durksen.com  Sun Apr 23 15:42:36 2006
From: brent at durksen.com (Brent Durksen)
Date: Sun, 23 Apr 2006 14:42:36 -0500
Subject: [Python Wpg] Sort a dictionary by values
Message-ID: <444BD8AC.3030308@durksen.com>

Hi,

I'll introduce myself, since this is my first time posting to the 
mailing list.  I'm a former student of Stuart's who keeps meaning to 
learn Python, but has been waiting for the right project to come along.  
Well, the NHL playoff season is upon us, which gave me as good a reason 
as any to write my first Python program.  I've created a short program 
to scrape TSN.ca's playoff points leader list, which I then use to add 
up the current scores of my friends' hockey pool and output the 
information in static HTML.  I run the program as a cron job to keep the 
scores current.  The result is visible at http://brent.homelinux.com/nhl/

If you view the results, you'll notice that they are not sorted.  I 
would like to do this, but have hit a conceptual roadblock.  The program 
uses a large dictionary with hockey player names as keys, and their 
point totals as the matching values.  Each of the pool contestants is 
represented by a list with their players' names, which is used to sum up 
their current standing using the dictionary.  In the excerpt below, p[1] 
represents a list of the hockey players chosen by a participant in the 
hockey pool, and d is the dictionary with the point totals:

    for i in range(len(p[1])):
        name = p[1][i] #Player's name
        try:
            points = int(d[name])
            total += points
        except:   # If the player's name is not found in the dictionary, 
indicate this with a * for debugging
            points = "0*"
    playerhtml += "<tr><td>%s</td><td>%s</td></tr>" % (name, points)

Like I said, I would like these results sorted.  As it is currently 
written, I am not keeping track of the results before generating the 
HTML, so there will be an additional step of creating a data structure 
for this information before I can get to sorting it.

I thought it might make sense to use a dictionary to store the 10 
players mapped to their point totals for each pool participant, then 
(somehow) sort the dictionary into a list/tuple by the values, instead 
of the keys.  But keep in mind that many of the values might be the same 
(5 of the 10 players might have three points), so functions I've read 
that simply reverse the key:value pairs, sort, then return a sorted list 
of the original keys will likely not work due to duplicate keys.

Could I create a list of tuples, e.g. t = (points, player) and sort the 
list by the first element in each tuple?  I'm not sure what that would 
look like.

I've hit a conceptual roadblock on this one.  If anyone is interested in 
reading the source code I've created (please be kind, it is my first 
Python program), it's available at 
http://brent.homelinux.com/nhl/nhlstats.py

I would appreciate any help you can offer!

Brent Durksen




From brent at durksen.com  Sun Apr 23 19:05:29 2006
From: brent at durksen.com (Brent Durksen)
Date: Sun, 23 Apr 2006 18:05:29 -0500
Subject: [Python Wpg] Sort a list of tuples!
Message-ID: <444C0839.1070303@durksen.com>

Hi again,

Well, I went on to answer my own question.  I created a list of tuples, 
in the format (points, name) and sorted the whole list, which was much 
easier than I expected.  That seems to sum up my first experience 
programming in Python: things are generally easier to accomplish than I 
would expect.

In any case, the source code is at 
http://brent.homelinux.com/nhl/nhlstats.py and if anyone wants to have a 
go at fixing my CPU consumption problem (someone familiar with the 
BeautifulSoup module, maybe) I would appreciate it.  I've commented what 
I perceive to be the cause of that problem in the source.

Thanks,

Brent Durksen


From stuartw at mts.net  Sun Apr 23 22:27:01 2006
From: stuartw at mts.net (Stuart Williams)
Date: Sun, 23 Apr 2006 21:27:01 -0500
Subject: [Python Wpg] Sort a list of tuples!
In-Reply-To: <444C0839.1070303@durksen.com>
References: <444C0839.1070303@durksen.com>
Message-ID: <17484.14197.338250.745670@gargle.gargle.HOWL>

>>>>> Brent Durksen writes:
> Subject: [Python Wpg] Sort a list of tuples!

> Well, I went on to answer my own question.  I created a list of tuples, 
> in the format (points, name) and sorted the whole list...

This is known as the Decorate Sort Undecorate (DSU) idiom in Python.
See for example http://wiki.python.org/moin/HowTo/Sorting or
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52234.

Python 2.4 added a key parameter to the built-in sort method which
internally uses DSU making this even easier.  Add itemgetter from the
operator module and you can do much of what you want with this:

  sorted(d.items(), key=operator.itemgetter(1), reverse=True)


Also Note that almost everywhere one sees "for i in range(len(foo)):"
one can replace it with "for item in foo:"

Stuart.


From umjenki5 at cc.umanitoba.ca  Mon Apr 24 13:18:09 2006
From: umjenki5 at cc.umanitoba.ca (Mark Jenkins)
Date: Mon, 24 Apr 2006 12:18:09 -0500
Subject: [Python Wpg] Sort a list of tuples!
In-Reply-To: <17484.14197.338250.745670@gargle.gargle.HOWL>
References: <444C0839.1070303@durksen.com>
	<17484.14197.338250.745670@gargle.gargle.HOWL>
Message-ID: <444D0851.8010303@cc.umanitoba.ca>

> Also Note that almost everywhere one sees "for i in range(len(foo)):"
> one can replace it with "for item in foo:"

Avoiding random access (list[#]) might make a big performance difference
too, I read that lists in emacs lisp are implemented as linked lists,
which made me wonder how python lists are implemented. Does anyone know?
(or have the time to find out?)

This reminds me of a related question, is there a nice pythonish way to
iterate through too equally sized lists in parallel?

# if it turns out that python lists are linked lists,
# this example would be really bad performance wise in
# big lists
for i, value in enumerate(list1):
    #do stuff to value and list2[i]


# an alternative
def two_iter_generator( iter1, iter2):
    iter1 = iter(iter1)
    iter2 = iter(iter2)
    try:
        while True:
            yield (iter1.next(), iter2.next() )
    except StopIteration: pass

for value1, value2 in two_iter_generator( range(10), range(10) ):
    # do stuff to value1 and value2


From jason at peaceworks.ca  Mon Apr 24 13:46:30 2006
From: jason at peaceworks.ca (Jason Hildebrand)
Date: Mon, 24 Apr 2006 12:46:30 -0500
Subject: [Python Wpg] Sort a list of tuples!
In-Reply-To: <444D0851.8010303@cc.umanitoba.ca>
References: <444C0839.1070303@durksen.com>
	<17484.14197.338250.745670@gargle.gargle.HOWL>
	<444D0851.8010303@cc.umanitoba.ca>
Message-ID: <1145900791.7975.251.camel@trotzdem.wpg.peaceworks.ca>

On Mon, 2006-04-24 at 12:18 -0500, Mark Jenkins wrote:
> This reminds me of a related question, is there a nice pythonish way to
> iterate through too equally sized lists in parallel?

If the lists are the exact same size, the builtin function zip() is
probably what you are looking for:

for item1, item2 in zip(list1, list2):
    # do stuff
    pass

peace,
Jason

-- 
Jason D. Hildebrand
T: 204 775 1212
E: jason at peaceworks.ca




From stuartw at mts.net  Mon Apr 24 22:00:53 2006
From: stuartw at mts.net (Stuart Williams)
Date: Mon, 24 Apr 2006 21:00:53 -0500
Subject: [Python Wpg] Sort a list of tuples!
In-Reply-To: <444D0851.8010303@cc.umanitoba.ca>
References: <444C0839.1070303@durksen.com>
	<17484.14197.338250.745670@gargle.gargle.HOWL>
	<444D0851.8010303@cc.umanitoba.ca>
Message-ID: <17485.33493.745331.1605@gargle.gargle.HOWL>

>>>>> Mark Jenkins writes:

> Avoiding random access (list[#]) might make a big performance
> difference too, I read that lists in emacs lisp are implemented as
> linked lists, which made me wonder how python lists are
> implemented. Does anyone know?  (or have the time to find out?)

Python lists are arrays allocated from the heap that are resized as
necessary, but when they grow memory is over-allocated (proportional
to the list size) to reduce the number of allocations on a list that
slowly grows, for example via append.

Stuart.


From stuartw at mts.net  Mon Apr 24 22:04:12 2006
From: stuartw at mts.net (Stuart Williams)
Date: Mon, 24 Apr 2006 21:04:12 -0500
Subject: [Python Wpg] Sort a list of tuples!
In-Reply-To: <1145900791.7975.251.camel@trotzdem.wpg.peaceworks.ca>
References: <444C0839.1070303@durksen.com>
	<17484.14197.338250.745670@gargle.gargle.HOWL>
	<444D0851.8010303@cc.umanitoba.ca>
	<1145900791.7975.251.camel@trotzdem.wpg.peaceworks.ca>
Message-ID: <17485.33692.957858.157652@gargle.gargle.HOWL>

>> This reminds me of a related question, is there a nice pythonish
>> way to iterate through too equally sized lists in parallel?

> If the lists are the exact same size, the builtin function zip() is
> probably what you are looking for...

There's also itertools.zip (and a bunch of friends) which handles long
lists like the two_iter_generator function Mark gave, building only as
necessary instead of up front.  This is also very useful for zipping
lists where one or more of the sequences being zipped isn't a list at
all but an iterator, for example reading a large file.

Stuart.


From stuartw at mts.net  Tue Apr 25 22:25:00 2006
From: stuartw at mts.net (Stuart Williams)
Date: Tue, 25 Apr 2006 21:25:00 -0500
Subject: [Python Wpg] Meeting reminder.
Message-ID: <17486.55804.729099.856585@gargle.gargle.HOWL>

Don't forget there's a meeting tomorrow night, details on the website.

Stuart.


From mpfaiffer at callapple.org  Wed Apr 26 00:25:36 2006
From: mpfaiffer at callapple.org (Mike Pfaiffer)
Date: Tue, 25 Apr 2006 23:25:36 -0500
Subject: [Python Wpg] Meeting reminder.
In-Reply-To: <17486.55804.729099.856585@gargle.gargle.HOWL>
References: <17486.55804.729099.856585@gargle.gargle.HOWL>
Message-ID: <200604252325.36600.mpfaiffer@callapple.org>

On April 25, 2006 09:25 pm, Stuart Williams wrote this amazing epistle:
> Don't forget there's a meeting tomorrow night, details on the website.
>
> Stuart.

 Don't forget folks, I'll be looking for some good suggestions for the 
program. ;-)

    Later
    Mike

-- 
+----------------------------------------------------------------------+
|Call-A.P.P.L.E. and the Digital Civilization http://www.callapple.org |
|   http://members.shaw.ca/pfaiffer = Mike Pfaiffer (B.A., B.Sc.)      |
+----------------------------------------------------------------------+
----- BEGIN GEEK CODE BLOCK -----
Version: 3.12
GCS/G/IT/PA/SS d s+:- a? C++ UL L++ W++ N++ o+ K- w(---) O+@ M++@ V PS+
PE !PGP t+ 5+ X R tv b+ DI+++ D++ G e++* h! r-- !y-- UF++
------ END GEEK CODE BLOCK ------


From jason at peaceworks.ca  Wed Apr 26 16:01:24 2006
From: jason at peaceworks.ca (Jason Hildebrand)
Date: Wed, 26 Apr 2006 15:01:24 -0500
Subject: [Python Wpg] starlanes instructions
In-Reply-To: <200604252325.36600.mpfaiffer@callapple.org>
References: <17486.55804.729099.856585@gargle.gargle.HOWL>
	<200604252325.36600.mpfaiffer@callapple.org>
Message-ID: <1146081684.2216.45.camel@trotzdem.wpg.peaceworks.ca>

On Tue, 2006-04-25 at 23:25 -0500, Mike Pfaiffer wrote:
> On April 25, 2006 09:25 pm, Stuart Williams wrote this amazing epistle:
> > Don't forget there's a meeting tomorrow night, details on the website.
>  Don't forget folks, I'll be looking for some good suggestions for the 
> program. ;-)

I've been trying to figure out how to play the game, and found a
different implementation of the game (in C) at
http://www.barnsdle.demon.co.uk/game/starlanes.html

I've attached the man page from from that version, which helps to
understand the gameplay.

Looks like an interesting game, Mike.

-- 
Jason D. Hildebrand
T: 204 775 1212
E: jason at peaceworks.ca

-------------- next part --------------



STARLANES(6)                                         STARLANES(6)


NAME
       starlanes - the game of starlanes

SYNOPSIS
       starlanes [-v|c|m]

DESCRIPTION
       Starlanes  is  a  game of interstellar commerce for 1 to 4
       players.  Players take two-phase turns: the first phase is
       movement, the second is trading.

       The object of the game is to become as wealthy as possible
       by trading and merging companies whilst out-smarting  your
       friends and enemies.

OPTIONS
       -v   Print version information

       -c   Force the game to play in color mode

       -m   Force the game to play in mono mode

PLAYING STARLANES
   The Starlanes User Interface
       Starlanes  is written using color ncurses, but will detect
       a black and  white  screen  and  will  modify  its  output
       accordingly.  On Linux, setting TERM=console or TERM=linux
       either on a virtual console or  in  a  color_xterm  window
       works well.

       After the initial player determination screen, you will be
       presented with the main Starlanes screen.  This screen  is
       split  into  three individual windows: the map window, the
       company window, and the general info window.

       The map window shows the terrain  of  the  universe.   The
       legend is:

              * - Star
              @ - Black hole
              + - Infant company
              . - Empty space
              A - Company A (Altair Starways)

       The  companies  are  Altair  Starways,  Beetlejuice  Ltd.,
       Capella Freight Co., Denebola Shippers, and Eridani  Expe-
       diters.   On the map, the companies are represented by the
       first letter of their name.

       The company window shows information concerning  the  cur-
       rently existing companies, including the company name, its
       price per share, and the current player's holdings.

       The general info window will prompt the user for input  if



Starlanes V1.2.2          29 March 1996                         1





STARLANES(6)                                         STARLANES(6)


       the player is waiting to move or trade, but will also dis-
       play special announcements as  they  come  up.   During  a
       player's  turn,  that  player's  name  is displayed in the
       title bar of the window, along with his cash holdings.

       Also, mention should be made of  two  other  windows:  the
       player standings window and the company detail window (not
       to be confused with the company info window.)

       The player standings window can be brought up  during  the
       player's  move by pressing the 's' key.  This window shows
       all the player's names, stock holdings,  cash,  and  total
       worth, sorted by total worth.  It also shows the number of
       sectors that remain to be filled by companies  before  the
       game ends.

       The company detail window is invoked with the 'c' key.  It
       shows, for each active company, its name, price per share,
       size,  and  total  worth  (all player's shares * price per
       share).  The company size and total worth  are  useful  in
       determining the result of a merger (see below.)

       If  a  screen redraw is necessary, pressing '^L' at almost
       any of the prompts will accomplish that.

       Finally, if the players  want  to  quit  before  the  game
       before  is over, press 'q' or '^C' and a quit verification
       window will pop up.  If 'y' is  pressed,  the  final  game
       standings will be displayed, and the program will end.

   Player Movement
       During  the  first  phase of a player's turn, the computer
       will prompt for a move from a choice of  5.   These  moves
       are chosen randomly (for the most part).  Upon making your
       move, there are several things that might happen.   (NOTE:
       it  is  important  to remember that two objects on the map
       are adjacent  only  if  they  are  orthogonally  adjacent.
       Diagonals don't count!)

       If you move into a sector that is completely surrounded by
       empty space (.), that sector will then contain  an  infant
       company (+).

       If  you  move next to an existing company (A-E), that com-
       pany will expand into that sector of the map.  If the  new
       extension  of  the  company touches an infant company (+),
       that infant company will also be assimilated.

       Given that you're not moving next to an existing  company,
       if you move next to a star (*) or an infant company (+), a
       new company will be formed.  You, as company founder, will
       receive 5 shares in the company for free.  For calculating
       how much a company will be  worth,  see  Company  Pricing,
       below.



Starlanes V1.2.2          29 March 1996                         2





STARLANES(6)                                         STARLANES(6)


       If  you  happen  to  move next to a black hole (@), one of
       many things could happen, depending on the  circumstances.
       See Black Holes, below.

   Company Pricing
       Determining  a company's price per share is fairly simple.
       Generally speaking, a company is worth $100 for every sec-
       tor it occupies (as given on the company info window under
       ``Size''), plus $500 for every sector it occupies which is
       adjacent  to  a  star  (*), minus $500 for every sector it
       occupies which is adjacent to a black hole (@).  If a com-
       pany's  price  per  share  drops to 0 or less, the company
       vanishes (see Black Holes, below.)   Also  note  that  you
       will  not  be  able to visually estimate a company's price
       per share if that company has undergone a stock split (see
       Stock Splits, below.)

   Holding Bonus
       Immediately  after  a  player's move, he is awarded a cash
       bonus equal to 5% of the total worth of his complete hold-
       ings.   This  bonus  is  awarded  even  if  the  game ends
       directly following the move (see Game's End, below.)  This
       is the cash that the player will then use during the trad-
       ing phase (see Trading, below.)

   Trading
       If any companies exist after a player moves  on  the  map,
       that  player  will  be  given  the  chance to buy and sell
       stock.  This is where the game is really played.  One must
       determine  which  companies  are going to earn the highest
       profits in the next round and invest  in  those  companies
       more  heavily  than  ones that only have a small chance of
       turning a profit.  (See  Strategy,  below.)   The  current
       player's  cash  value  is  printed next to his name in the
       general info window title.

       Use the arrow keys to select a company you wish  to  trade
       stock  in,  then  press  return.  You will be asked for an
       amount to trade.  Enter the number of shares you  wish  to
       purchase  in  this  company.   (Just press return again or
       enter ``0'' if you don't really want to  trade  with  this
       company.)   Choose  a  negative amount if you want to sell
       shares (at 100% of their value.)  At this point, the  user
       can  also press the 'm' key to purchase the maximum number
       of shares possible, or press the 'n' key to  sell  all  of
       his holdings in this company.

       Once the player has completed trading, he can press escape
       to end his turn, thereby transferring control to the  next
       player.

   Mergers
       When a player chooses a sector of the map that would cause
       two or more companies to touch, a merger occurs.



Starlanes V1.2.2          29 March 1996                         3





STARLANES(6)                                         STARLANES(6)


       First, the companies sizes are  checked  and  the  company
       with the larger size absorbs the smaller.

       If  the  companies are the same size, the company with the
       highest total worth absorbs the smaller.   (The  user  can
       view  company  size and company total worth on the company
       detail window, see above.)

       Finally, if both company sizes and total worths match, the
       companies will merge at random.

       If a three or four-way merger occurs, the merges will take
       place one at a time, in an order that is  somewhat  clock-
       wise.

       After  a  merger, each player will have half the number of
       shares of held in the vanquished company added to the num-
       ber  of  shares  held  in the still-existing company.  The
       value of the still-existing company's price per share will
       increase by the vanquished company's price per share.

       Additionally, each player receives a cash bonus equal to

              10 * stock price * holdings percentage,

       where  stock  price is the old price per share of the van-
       quished company and holdings percentage is the  percentage
       of  total stock once owned in the vanquished company.  For
       example, imagine that  Altair  Starways  (worth  $500  per
       share)  is  merged  into  Denebola Shippers.  Also, assume
       that the player owned 50% of the total  shares  in  Altair
       Starways.   Using the formula, that player would receive a
       bonus of

              10 * $500 * 50% = $2,500.

       For more hints on how to deal with mergers, see  Strategy,
       below.

   Stock Splits
       When  a  company's  price per share climbs above $3,000, a
       stock split occurs.  All player holdings in  that  company
       are  doubled,  and  the  price  per  share is halved.  See
       Strategy, below, for money making tips  during  and  after
       stock splits.

   Black Holes
       Since  black  holes drain $500 from any company that is in
       contact with them, it is possible that the company's price
       per  share  will  drop to 0 or less.  If this happens, the
       entire company is sucked out of space and all player hold-
       ings are lost.

       If a player attempts to place an infant company (+) near a



Starlanes V1.2.2          29 March 1996                         4





STARLANES(6)                                         STARLANES(6)


       black hole (@), that infant company  will  be  immediately
       sucked up, resulting again in an empty sector.

       Likewise, if a player attempts to start a new company that
       would normally be worth $500 or less per share next  to  a
       black  hole,  the  sectors that the new company would have
       occupied all become empty space (.).

       For some ways to make black holes work to your  advantage,
       see Strategy, below.

   Game's End
       The game ends when 54% of the map is filled with companies
       (about 70 sectors.)  The player who made  the  final  move
       receives  his 5% holdings bonus (see Holding Bonus, above)
       and the final standings window is displayed.   The  player
       with the highest total worth is the winner.

   Strategy
       In  order to maximize your profits, you must wisely invent
       your cash.  For instance, if a company  is  near  a  black
       hole, it is likely that it will lose $500 per share in the
       next few rounds.  Likewise, if a company is near  a  star,
       it might soon have a $500 gain.

       Also, the larger the company, the greater that chance that
       it will be added onto (just because it takes up more  room
       on  the map.)  If you own 300 shares in a company, and its
       value goes up by $100 per share, that's a $30,000 increase
       in your net worth.

       Another  thing to watch for is when companies are about to
       merge.  Remember that the number of shares you own in  the
       smaller  company  will be halved before being added to the
       bigger one when they merge.  This  can  be  used  to  your
       advantage, especially if the smaller company is worth sig-
       nificantly less than the larger.  If the  big  company  is
       worth  $2,000  per  share, and the small is worth $200 per
       share, you can buy 10 times as many shares in the smaller.
       When  the  companies  merge,  the  number of shares in the
       smaller company is halved, but  it's  still  5  times  the
       amount  of stock you could've purchased in the larger com-
       pany.

       Don't forget that when two companies  merge,  the  players
       receive  a  cash  bonus  that depends on the percentage of
       stock they owned in  the  smaller  company  (see  Mergers,
       above.)  It is good to try to own a higher percentage than
       anyone else.

       A way to gain profit earning potential is to have a  large
       number  of  shares in a company when the stock splits two-
       for-one (see Stock Splits, above.)  Even though your  ini-
       tial  net  worth  remains  the  same  after a stock split,



Starlanes V1.2.2          29 March 1996                         5





STARLANES(6)                                         STARLANES(6)


       you'll now increase your net worth by twice the value  you
       used  to  whenever  the  company's  price per share rises.
       Also, if your opponent has 100 shares  and  you  have  150
       before  the  split,  that'll  change to 200 shares and 300
       shares, effectively increasing  your  lead  in  shares  by
       100%.

       Black holes weren't present in the original game, but were
       added to give players who have fallen behind a  chance  to
       shaft  the  leaders.   If your opponent owns 100 shares of
       Altair Starways and you only own 50, you  can  extend  the
       company  against  a  black  hole.  Your opponent will lose
       $50,000 from his net worth, but you'll only lose  $25,000.

       Finally,  a reminder to invest as much money as you possi-
       ble can each round (unless it's too  risky.)   The  reason
       for  this  is  the  5% cash bonus all players receive each
       round based on their holdings (see Holdings Bonus, above.)
       Your cash earns you no interest.

FILES
       /usr/local/games/starlanes
       /usr/local/man/man6/starlanes.6

AUTHOR
       This version of Starlanes was written and is Copyright (C)
       by Brian ``Beej''  Hall  1995-1997.   The  author  can  be
       reached  at  beej at ecst.csuchico.edu.  Starlanes comes with
       ABSOLUTELY NO WARRANTY.  This is free  software,  and  you
       are  welcome  to redistribute it under certain conditions;
       read the file COPYING for details.

ACKNOWLEDGMENTS
       I'd like to thank the  unnamed  authors  of  the  original
       Starlanes for creating such a thought provoking and fun to
       play text-based game.  I got my  first  copy  on  a  First
       Osborne  Group  (FOG)  disk in what must have been 1982 or
       so, and used to spend endless  hours  playing  against  my
       friends.  For us, the game is just as fun as ever.  To the
       original authors, I salute you!

BUGS
       There are no computer controlled players.

       Doesn't respond if ^Z is pressed to suspend the game.

       If only one person is playing, he or she  will  frequently
       make  enough money to break the fixed-field-length windows
       and/or cause the variable that holds player cash to  over-
       flow.   Try to keep your earnings under $2 billion until I
       convert these variables to long doubles.  :-)






Starlanes V1.2.2          29 March 1996                         6



From mpfaiffer at callapple.org  Wed Apr 26 23:56:15 2006
From: mpfaiffer at callapple.org (Mike Pfaiffer)
Date: Wed, 26 Apr 2006 22:56:15 -0500
Subject: [Python Wpg] starlanes instructions
In-Reply-To: <1146081684.2216.45.camel@trotzdem.wpg.peaceworks.ca>
References: <1146081684.2216.45.camel@trotzdem.wpg.peaceworks.ca>
Message-ID: <200604262256.15629.mpfaiffer@callapple.org>

On April 26, 2006 03:01 pm, Jason Hildebrand wrote this amazing epistle:

> I've attached the man page from from that version, which helps to
> understand the gameplay.

 Pretty cool. I think I'll make the instructions part of the introduction. I 
don't recall some of the features from the man page in the Apple// version. I 
think for v1.2 I'll concentrate on cleaning up the code and implementing the 
parts of the suggestions I understand. As Stuart suggested, small steps. For 
v1.4 I'll see about implementing more features.

 I'll fix the missing print statement at the end and upload the change before 
morning (or everybody can make the change in their code). I'll keep the same 
file name and permissions.

    Later
    Mike



-- 
+----------------------------------------------------------------------+
|Call-A.P.P.L.E. and the Digital Civilization http://www.callapple.org |
|   http://members.shaw.ca/pfaiffer = Mike Pfaiffer (B.A., B.Sc.)      |
+----------------------------------------------------------------------+
----- BEGIN GEEK CODE BLOCK -----
Version: 3.12
GCS/G/IT/PA/SS d s+:- a? C++ UL L++ W++ N++ o+ K- w(---) O+@ M++@ V PS+
PE !PGP t+ 5+ X R tv b+ DI+++ D++ G e++* h! r-- !y-- UF++
------ END GEEK CODE BLOCK ------


From sbalneav at legalaid.mb.ca  Thu Apr 27 09:56:10 2006
From: sbalneav at legalaid.mb.ca (Scott Balneaves)
Date: Thu, 27 Apr 2006 08:56:10 -0500
Subject: [Python Wpg] LdapFS.py,
	now with improved Bio-Scrubbing (tm) Action!!
Message-ID: <20060427135610.GA4923@localdomain>

Or not.

Reading/writing works (mostly) bug (somewhere) in utime, etc etc etc.

One of the things which we'll need to look at eventually, in order to
PROPERLY do things, is to actually use the python-ldap goodies to
actually look at the schema definitions for various attributes within
the LDAP database.  For instance, for now, creating an empty attribute
(via touch) doesn't actually go and do anything to the LDAP datastore,
because most attributes in an LDAP database don't allow for null
entries.  But, (you guessed it) some do.  Right now, to be safe, null
attr's are just kept track of in a list (cleverly named "null_attrs" to
hide it's true nefarious intentions), and actually move out to the
database when they get "promoted" to real attrs by virtue of having real
data put in them.  It would be nice to eventually handle this
"properly", however, for a 0.1 release, I'm not sure if it's absolutely
necessary.

As well, I'm not currently handling segmented writing.  Within FUSE,
with the _write callout, it's quite common to get passed a block of 2048
bytes of data to be written at offset 0x00800000, or some such
happiness.  Now, careful perusal of my code will show that 1) I've no
real clue as to what I'm doing, and 2) I'm simply rewriting the the
entire attribute with what I get passed.  This works (nominally) because
FUSE reads/writes in 2048 blocks, and most attributes are lucky if they
break 80 characters, so the end result is that you simply get passed
everything anyway, so it works.

It's not RIGHT though, gosh-durnit, and we should handle this correctly,
for some varying value of "correct", as yet to be determined.  As well,
note that values from the LDAP calls return lists of strings, and my
crafty conversion from/to newline separated text.

That's all for now fellow passel-tongues, or snake charmers, or ministry
of funny walkers, or whatever we in the Python community call ourselves
(perlites are "monks" IIRC).

Cheers!

Scott

-- 
Scott L. Balneaves | "Looking beyond the embers of bridges glowing behind us
Systems Department |  To a glimpse of how green it was on the other side..."
Legal Aid Manitoba |    -- Pink Floyd "High Hopes"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LdapFS.py
Type: text/x-python
Size: 9855 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060427/3c1ab0a1/attachment.py>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/winnipeg/attachments/20060427/3c1ab0a1/attachment.sig>

From stuartw at mts.net  Fri Apr 28 08:09:59 2006
From: stuartw at mts.net (Stuart Williams)
Date: Fri, 28 Apr 2006 07:09:59 -0500
Subject: [Python Wpg] sort vs. sorted
Message-ID: <17490.1559.558264.784373@gargle.gargle.HOWL>

On Wednesday some of us were confused by sort vs. sorted, and
specifically why the sorted() method isn't found in a list:

>>> alist = [1, 3, 2]
>>> alist.sort()
>>> alist
[1, 2, 3]
>>> alist.sorted()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'list' object has no attribute 'sorted'
>>> alist = [1, 3, 2]
>>> sorted(alist)
[1, 2, 3]

sort() is a method of list.  As explained, it sorts the list in place
and it does not return the list as a reminder of that fact.

sorted() is a builtin function, not a method on list, because it's
more general taking any iterator as its first argument (for example an
open file), not just a list.  It of course does return a list.

Stuart.




From stuartw at mts.net  Fri Apr 28 16:13:20 2006
From: stuartw at mts.net (Stuart Williams)
Date: Fri, 28 Apr 2006 15:13:20 -0500
Subject: [Python Wpg] More on hating brackets, commas, and quotes
Message-ID: <17490.30560.181447.259073@gargle.gargle.HOWL>

Bill and others,

I mentioned at Tuesday's meeting how to use a regular expression to
split text on indentations to stuff into a nested list.  See below for
how that works - very similar to the code we saw at the meeting.

Hmmm... I wonder how many people will stumble upon this message doing
web searches for the names of the hockey players in the sample data.

Stuart.


import pprint
import re

fan_data = """
Charles
 Daniel Alfredsson
 Pavel Datsyuk
 Mike Modano
 Steve Bernier
Jeff
 Joe Thornton
 Eric Staal
Adam
 Jonathan Cheechoo
 Jere Lehtinen
 Michael Ryder
 Patrick Marleau
"""

fans = []
# strip leading and trailing newline(s) and split on un-indented entries
for para in re.split(r'\n\b', fan_data.strip()):
    lines = para.split('\n')
    # create tuple of first line followed by list of stripped remaining lines
    fans.append((lines[0],
               [player.strip() for player in lines[1:]]))

pprint.pprint(fans)