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 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: 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: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: 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: 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: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: 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 += "%s%s" % (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: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: 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 "", 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)