assorted-commits Mailing List for Assorted projects (Page 19)
Brought to you by:
yangzhang
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(9) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(86) |
Feb
(265) |
Mar
(96) |
Apr
(47) |
May
(136) |
Jun
(28) |
Jul
(57) |
Aug
(42) |
Sep
(20) |
Oct
(67) |
Nov
(37) |
Dec
(34) |
2009 |
Jan
(39) |
Feb
(85) |
Mar
(96) |
Apr
(24) |
May
(82) |
Jun
(13) |
Jul
(10) |
Aug
(8) |
Sep
(2) |
Oct
(20) |
Nov
(31) |
Dec
(17) |
2010 |
Jan
(16) |
Feb
(11) |
Mar
(17) |
Apr
(53) |
May
(31) |
Jun
(13) |
Jul
(3) |
Aug
(6) |
Sep
(11) |
Oct
(4) |
Nov
(17) |
Dec
(17) |
2011 |
Jan
(3) |
Feb
(19) |
Mar
(5) |
Apr
(17) |
May
(3) |
Jun
(4) |
Jul
(14) |
Aug
(3) |
Sep
(2) |
Oct
(1) |
Nov
(3) |
Dec
(2) |
2012 |
Jan
(3) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
(4) |
Aug
(5) |
Sep
(2) |
Oct
(3) |
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
(9) |
Apr
(5) |
May
|
Jun
(2) |
Jul
(1) |
Aug
(10) |
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
(3) |
Mar
(3) |
Apr
(1) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2016 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <yan...@us...> - 2009-06-06 22:49:19
|
Revision: 1452 http://assorted.svn.sourceforge.net/assorted/?rev=1452&view=rev Author: yangzhang Date: 2009-06-06 22:48:41 +0000 (Sat, 06 Jun 2009) Log Message: ----------- ready to release 0.2 Modified Paths: -------------- mailing-list-filter/trunk/README mailing-list-filter/trunk/publish.bash mailing-list-filter/trunk/setup.py Modified: mailing-list-filter/trunk/README =================================================================== --- mailing-list-filter/trunk/README 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/trunk/README 2009-06-06 22:48:41 UTC (rev 1452) @@ -54,9 +54,19 @@ Sent as having been sent by you. This is presumably how most other IMAP servers work. -- Implement incremental maintenance of local cache. - - Accept custom operations for filtered/unfiltered messages (trashing/untrashing, labeling/unlabeling, etc.). - Refactor the message fetching/management part out into its own library. + +Changes +------- + +v0.2 + +- Added disk-based operation to remove memory capacity limit. +- Added incremental updates to local cache. + +v0.1 + +- Initial release: fully in-memory operation and no incremental updates. Modified: mailing-list-filter/trunk/publish.bash =================================================================== --- mailing-list-filter/trunk/publish.bash 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/trunk/publish.bash 2009-06-06 22:48:41 UTC (rev 1452) @@ -1,8 +1,8 @@ #!/usr/bin/env bash fullname='Mailing List Filter' -version=0.1 -license=gpl +version=0.2 +license=gpl3 websrcs=( README ) rels=( pypi: ) . assorted.bash "$@" Modified: mailing-list-filter/trunk/setup.py =================================================================== --- mailing-list-filter/trunk/setup.py 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/trunk/setup.py 2009-06-06 22:48:41 UTC (rev 1452) @@ -5,7 +5,7 @@ pkg_info_text = """ Metadata-Version: 1.1 Name: mailing-list-filter -Version: 0.1 +Version: 0.2 Author: Yang Zhang Author-email: yaaang NOSPAM at REMOVECAPS gmail Home-page: http://assorted.sourceforge.net/mailing-list-filter/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:52:14
|
Revision: 1451 http://assorted.svn.sourceforge.net/assorted/?rev=1451&view=rev Author: yangzhang Date: 2009-06-03 17:52:11 +0000 (Wed, 03 Jun 2009) Log Message: ----------- updated version numbers and changelog Modified Paths: -------------- python-commons/trunk/README python-commons/trunk/publish.bash python-commons/trunk/setup.py python-commons/trunk/src/commons/__init__.py Modified: python-commons/trunk/README =================================================================== --- python-commons/trunk/README 2009-06-03 17:37:26 UTC (rev 1450) +++ python-commons/trunk/README 2009-06-03 17:52:11 UTC (rev 1451) @@ -39,9 +39,25 @@ version 0.6, 2008-10-?? -- ??? (review!) -- released for [MIT 6.00 courseware](http://assorted.sf.net/mit600/) +- to strs added unwrap, indent, unindent, remove_empty_lines, underline, + dos2unix, quotejs, unicode2html, html2unicode, nat_lang_join, or_join, + and_join +- to misc added sendmail, days, settimeout, run, TerminalController +- imported and updated jorendorff's path.py +- to startup added command_name +- to files added read_file, write_file, write_or_rm, is_nonempty_file +- added sqlhash and sqlhash backend for shelf +- to structs added dicts2structs, structs2dicts; FreeStruct renamed to + free_struct +- to seqs added span, group_as_subseqs +- decs.pickle_memoized uses protocol 2 +- general tweaks; epydoc fixes +- python 2.6-ready +- released for [Mailing List Filter], [MIT 6.00] courseware +[Mailing List Filter]: http://assorted.sourceforge.net/mailing-list-filter/ +[MIT 6.00]: http://web.mit.edu/~6.00/ + version 0.5, 2008-05-14 - added `cp1252_to_unicode()` Modified: python-commons/trunk/publish.bash =================================================================== --- python-commons/trunk/publish.bash 2009-06-03 17:37:26 UTC (rev 1450) +++ python-commons/trunk/publish.bash 2009-06-03 17:52:11 UTC (rev 1451) @@ -1,14 +1,14 @@ #!/usr/bin/env bash post-stage() { - epydoc -o $stagedir/doc src/commons/ + epydoc -v -o $stagedir/doc src/commons/ } echo 'Remember to keep versions in sync in all three locations:' echo '__init__.py, README (Changes), setup.bash, and setup.py' fullname='Python Commons' -version=0.5 +version=0.6 license=psf websrcs=( README ) rels=( pypi: ) Modified: python-commons/trunk/setup.py =================================================================== --- python-commons/trunk/setup.py 2009-06-03 17:37:26 UTC (rev 1450) +++ python-commons/trunk/setup.py 2009-06-03 17:52:11 UTC (rev 1451) @@ -9,7 +9,7 @@ pkg_info_text = """ Metadata-Version: 1.1 Name: python-commons -Version: 0.5 +Version: 0.6 Author: Yang Zhang Author-email: yaaang NOSPAM at REMOVECAPS gmail Home-page: http://assorted.sourceforge.net/python-commons Modified: python-commons/trunk/src/commons/__init__.py =================================================================== --- python-commons/trunk/src/commons/__init__.py 2009-06-03 17:37:26 UTC (rev 1450) +++ python-commons/trunk/src/commons/__init__.py 2009-06-03 17:52:11 UTC (rev 1451) @@ -10,7 +10,7 @@ @license: PSF """ -__version__ = ( 0, 5, 0 ) +__version__ = ( 0, 6, 0 ) __all__ = [ 'async', 'control', 'decs', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:37:34
|
Revision: 1450 http://assorted.svn.sourceforge.net/assorted/?rev=1450&view=rev Author: yangzhang Date: 2009-06-03 17:37:26 +0000 (Wed, 03 Jun 2009) Log Message: ----------- fixed documentation issues Modified Paths: -------------- python-commons/trunk/src/commons/async.py python-commons/trunk/src/commons/control.py python-commons/trunk/src/commons/decs.py python-commons/trunk/src/commons/files.py python-commons/trunk/src/commons/log.py python-commons/trunk/src/commons/misc.py python-commons/trunk/src/commons/path.py python-commons/trunk/src/commons/seqs.py python-commons/trunk/src/commons/servers.py python-commons/trunk/src/commons/sqlhash.py python-commons/trunk/src/commons/startup.py Modified: python-commons/trunk/src/commons/async.py =================================================================== --- python-commons/trunk/src/commons/async.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/async.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -15,7 +15,7 @@ @param seconds: The amount of time in seconds to sleep. @type seconds: float - @return: The L{defer.Deferred} that will be fired on wake-up. + @return: The C{defer.Deferred} that will be fired on wake-up. @rtype: defer.Deferred """ d = defer.Deferred() Modified: python-commons/trunk/src/commons/control.py =================================================================== --- python-commons/trunk/src/commons/control.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/control.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -17,7 +17,7 @@ @classmethod def sleep( cls ): """ - Calls L{time.sleep} for 100000 seconds at a time in a + Calls C{time.sleep} for 100000 seconds at a time in a while-true loop. """ while True: Modified: python-commons/trunk/src/commons/decs.py =================================================================== --- python-commons/trunk/src/commons/decs.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/decs.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -76,7 +76,7 @@ to return anything. Also, if the procedure returns a boolean, it will be wrapped in - L{xmlrpclib.Boolean}. + C{xmlrpclib.Boolean}. @param func: The procedure to decorate. @type func: function @@ -119,7 +119,7 @@ @param deserializer: The function te deserialize the cache file contents into the return value. This should take the file object and return a string. - type: deserializer: function + @type deserializer: function @param pathfunc: Returns the path where the files should be saved. This should be able to take the same arguments as the original Modified: python-commons/trunk/src/commons/files.py =================================================================== --- python-commons/trunk/src/commons/files.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/files.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -67,7 +67,7 @@ @param do_create_subdir: If C{True}, then creates a sub-sub-directory within the temporary sub-directory (and returns the path to that). The sub-sub-directory's name is randomized - (uses L{tempfile.mkdtemp}). + (uses C{tempfile.mkdtemp}). @type do_create_subdir: bool @return: The path to the temporary (sub-)sub-directory. Modified: python-commons/trunk/src/commons/log.py =================================================================== --- python-commons/trunk/src/commons/log.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/log.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -57,7 +57,7 @@ def tailor_logs( flag, *prefix ): """ - Avoid repetitive typing! Usage: + Avoid repetitive typing! Usage:: debug,info,warning,_,_ = tailor_logs('myflag','some','prefix') """ @@ -94,7 +94,7 @@ @type do_server: bool @param flags: The set of flags on which to lower the threshold to - L{logging.DEBUG}. + C{logging.DEBUG}. @type flags: iterable @param path: The path of the log file (only considered if Modified: python-commons/trunk/src/commons/misc.py =================================================================== --- python-commons/trunk/src/commons/misc.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/misc.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -79,15 +79,15 @@ """ A simple timer for code sections. - @param output: The resulting time is put into index 0 of L{output}. - @type output: index-writeable + Example:: - Example: + t = [0] + with wall_clock(t): + sleep(1) + print "the sleep operation took %d seconds" % t[0] - t = [0] - with wall_clock(t): - sleep(1) - print "the sleep operation took %d seconds" % t[0] + @param output: The resulting time is put into index 0 of C{output}. + @type output: index-writeable """ start = time() try: Modified: python-commons/trunk/src/commons/path.py =================================================================== --- python-commons/trunk/src/commons/path.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/path.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -1,19 +1,20 @@ """ path.py - An object representing a path to a file or directory. -Example: +Example:: -from path import path -d = path('/home/guido/bin') -for f in d.files('*.py'): + from path import path + d = path('/home/guido/bin') + for f in d.files('*.py'): f.chmod(0755) This module requires Python 2.6 or later. URL: http://www.jorendorff.com/articles/python/path -Author: Jason Orendorff <jason.orendorff\x40gmail\x2ecom> (and others - see the url!) - Yang Zhang <yaaang\x40gmail\x2ecom> -Date: 2009 + +@author: Jason Orendorff <jason.orendorff\x40gmail\x2ecom> (and others - see the url!) +@author: Yang Zhang <yaaang\x40gmail\x2ecom> +@date: 2009 """ @@ -497,15 +498,14 @@ def fnmatch(self, pattern): """ Return True if self.name matches the given pattern. - pattern - A filename pattern with wildcards, - for example '*.py'. + @param pattern: A filename pattern with wildcards, for example '*.py'. """ return fnmatch.fnmatch(self.name, pattern) def glob(self, pattern): """ Return a list of path objects that match the pattern. - pattern - a path relative to this directory, with wildcards. + @param pattern: A path relative to this directory, with wildcards. For example, path('/users').glob('*/bin/*') returns a list of all the files users have in their bin directories. @@ -552,11 +552,11 @@ Optional arguments: - encoding - The Unicode encoding (or character set) of + @param encoding: The Unicode encoding (or character set) of the file. If present, the content of the file is decoded and returned as a unicode object; otherwise it is returned as an 8-bit str. - errors - How to handle Unicode errors; see help(str.decode) + @param errors: How to handle Unicode errors; see help(str.decode) for the options. Default is 'strict'. """ if encoding is None: @@ -673,19 +673,18 @@ def lines(self, encoding=None, errors='strict', retain=True): r""" Open this file, read all lines, return them in a list. - Optional arguments: - encoding - The Unicode encoding (or character set) of + This uses 'U' mode in Python 2.3 and later. + + @param encoding: The Unicode encoding (or character set) of the file. The default is None, meaning the content of the file is read as 8-bit characters and returned as a list of (non-Unicode) str objects. - errors - How to handle Unicode errors; see help(str.decode) + @param errors: How to handle Unicode errors; see help(str.decode) for the options. Default is 'strict' - retain - If true, retain newline characters; but all newline + @param retain: If true, retain newline characters; but all newline character combinations ('\r', '\n', '\r\n') are translated to '\n'. If false, newline characters are stripped off. Default is True. - - This uses 'U' mode in Python 2.3 and later. """ if encoding is None and retain: f = self.open(_textmode) @@ -705,15 +704,15 @@ This puts a platform-specific newline sequence on every line. See 'linesep' below. - lines - A list of strings. + @param lines: A list of strings. - encoding - A Unicode encoding to use. This applies only if + @param encoding: A Unicode encoding to use. This applies only if 'lines' contains any Unicode strings. - errors - How to handle errors in Unicode encoding. This + @param errors: How to handle errors in Unicode encoding. This also applies only to Unicode strings. - linesep - The desired line-ending. This line-ending is + @param linesep: The desired line-ending. This line-ending is applied to every line. If a line already has any standard line ending ('\r', '\n', '\r\n', u'\x85', u'\r\x85', u'\u2028'), that will be stripped off and @@ -722,13 +721,13 @@ Unix, etc.) Specify None to write the lines as-is, like file.writelines(). - Use the keyword argument append=True to append lines to the - file. The default is to overwrite the file. Warning: - When you use this with Unicode data, if the encoding of the - existing data in the file is different from the encoding - you specify with the encoding= parameter, the result is - mixed-encoding data, which can really confuse someone trying - to read the file later. + @param append: Append lines to the + file. The default is to overwrite the file. Warning: + When you use this with Unicode data, if the encoding of the + existing data in the file is different from the encoding + you specify with the encoding= parameter, the result is + mixed-encoding data, which can really confuse someone trying + to read the file later. """ if append: mode = 'ab' Modified: python-commons/trunk/src/commons/seqs.py =================================================================== --- python-commons/trunk/src/commons/seqs.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/seqs.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -50,7 +50,7 @@ """ Given a reader function L{read}, reads in pickled objects from it. I am a generator which yields unpickled objects. I assume that the pickling - is "safe," done using L{safe_pickle}. + is "safe," done using L{safe_pickler}. @param read: The reader function that reads from a stream. It should take a single argument, the number of bytes to consume. @@ -220,7 +220,7 @@ @return: The next number in the sequence. @rtype: int - @throw ClosedError: If I was previously L{close}d. + @raise ClosedError: If I was previously L{close}d. """ if self.log is None: raise ClosedError() @@ -239,7 +239,7 @@ L{seqno}). @rtype: int - @throw ClosedError: If I was previously L{close}d. + @raise ClosedError: If I was previously L{close}d. """ if self.log is None: raise ClosedError() @@ -315,7 +315,7 @@ def flatten( stream ): """ - For each item yielded by L{gen}, if that item is itself an + For each item yielded by L{stream}, if that item is itself an iterator/generator, then I will recurse into C{flatten(gen)}; otherwise, I'll yield the yielded item. Thus, I essentially "flatten" out a tree of iterators. Modified: python-commons/trunk/src/commons/servers.py =================================================================== --- python-commons/trunk/src/commons/servers.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/servers.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -85,7 +85,7 @@ def __init__( self, timeout, do_catch ): """ - @param timeout: The amount of time to spend in L{select.select}. + @param timeout: The amount of time to spend in C{select.select}. @type timeout: int @param do_catch: Whether exceptions should be swallowed in the loop. @@ -143,7 +143,7 @@ Base class for stoppable TCP stream servers. This class supports interrupts because it times out the blocking call to - L{select.select}, and checks whether the program is terminating. + C{select.select}, and checks whether the program is terminating. """ allow_reuse_address = True Modified: python-commons/trunk/src/commons/sqlhash.py =================================================================== --- python-commons/trunk/src/commons/sqlhash.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/sqlhash.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -6,12 +6,11 @@ used they are implicitly converted to the default encoding before being stored. -Issues: - - # ??? how to coordinate with whichdb - # ??? Size of text fields fixed or varchar (do we need blobs) - # ??? does default encoding affect str-->bytes or PySqlite3 always use UTF-8 - # ??? if pure python overhead and pysqlite overhead is too high, rewrite in C +@todo Issues: + - ??? how to coordinate with whichdb + - ??? Size of text fields fixed or varchar (do we need blobs) + - ??? does default encoding affect str-->bytes or PySqlite3 always use UTF-8 + - ??? if pure python overhead and pysqlite overhead is too high, rewrite in C ''' __all__ = ['error', 'open'] Modified: python-commons/trunk/src/commons/startup.py =================================================================== --- python-commons/trunk/src/commons/startup.py 2009-06-03 17:13:32 UTC (rev 1449) +++ python-commons/trunk/src/commons/startup.py 2009-06-03 17:37:26 UTC (rev 1450) @@ -122,9 +122,9 @@ """ A feature-ful program starter. Configures logging and psyco, then runs the C{main} function defined in the caller's module, passing - in L{sys.argv}. If the C{PYDBG} environment variable is set, then - runs C{main} in L{pdb}. If the C{PYPROF} environment variable is - set, then runs C{main} in L{profile}. Finally, exits with + in C{sys.argv}. If the C{PYDBG} environment variable is set, then + runs C{main} in C{pdb}. If the C{PYPROF} environment variable is + set, then runs C{main} in C{cProfile}. Finally, exits with C{main}'s return value. For example:: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:13:40
|
Revision: 1449 http://assorted.svn.sourceforge.net/assorted/?rev=1449&view=rev Author: yangzhang Date: 2009-06-03 17:13:32 +0000 (Wed, 03 Jun 2009) Log Message: ----------- fixed stray export Modified Paths: -------------- python-commons/trunk/src/commons/misc.py Modified: python-commons/trunk/src/commons/misc.py =================================================================== --- python-commons/trunk/src/commons/misc.py 2009-06-03 17:09:40 UTC (rev 1448) +++ python-commons/trunk/src/commons/misc.py 2009-06-03 17:13:32 UTC (rev 1449) @@ -16,7 +16,6 @@ sendmail seq settimeout -tc timeout_exception wall_clock '''.split() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:09:40
|
Revision: 1448 http://assorted.svn.sourceforge.net/assorted/?rev=1448&view=rev Author: yangzhang Date: 2009-06-03 17:09:40 +0000 (Wed, 03 Jun 2009) Log Message: ----------- explicit exports Modified Paths: -------------- python-commons/trunk/src/commons/log.py Modified: python-commons/trunk/src/commons/log.py =================================================================== --- python-commons/trunk/src/commons/log.py 2009-06-03 17:09:35 UTC (rev 1447) +++ python-commons/trunk/src/commons/log.py 2009-06-03 17:09:40 UTC (rev 1448) @@ -12,6 +12,19 @@ import logging, logging.handlers, sys from logging import getLogger +__all__ = """ +fmt +log +exception +critical +error +warning +info +die +tailor_logs +config_logging +""".split() + # TODO cleanup / reorganize this section def fmt( flag, *args ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:09:36
|
Revision: 1447 http://assorted.svn.sourceforge.net/assorted/?rev=1447&view=rev Author: yangzhang Date: 2009-06-03 17:09:35 +0000 (Wed, 03 Jun 2009) Log Message: ----------- fixes and tweaks to shelf Modified Paths: -------------- python-commons/trunk/src/commons/sqlhash.py Modified: python-commons/trunk/src/commons/sqlhash.py =================================================================== --- python-commons/trunk/src/commons/sqlhash.py 2009-06-03 17:08:19 UTC (rev 1446) +++ python-commons/trunk/src/commons/sqlhash.py 2009-06-03 17:09:35 UTC (rev 1447) @@ -64,7 +64,7 @@ item = self.conn.execute(GET_ITEM, (sqlite3.Binary(key),)).fetchone() if item is None: raise KeyError(key) - return item[0] + return str(item[0]) def __setitem__(self, key, value): ADD_ITEM = 'REPLACE INTO shelf (key, value) VALUES (?,?)' @@ -131,17 +131,40 @@ return SQLhash() class Shelf(shelve.Shelf): + def __init__(self, *args, **okwargs): + kwargs = okwargs.copy() + try: del kwargs['cache'] + except KeyError: pass + shelve.Shelf.__init__(self, *args, **kwargs) + if not okwargs.get('cache', True): self.cache = None + def __getitem__(self, k): + val = lambda: cPickle.loads(self.dict[k]) + if self.cache is None: + return val() + else: + try: return self.cache[k] + except KeyError: return self.cache.setdefault(k, val()) def __setitem__(self, key, value): - if self.writeback: self.cache[key] = value + if self.cache is not None and self.writeback: self.cache[key] = value else: self.dict[key] = cPickle.dumps(value, self._protocol) def __delitem__(self, key): try: del self.dict[key] except: + if not self.writeback: raise + # If writeback is enabled then it's OK if it's missing in the + # underlying dict but present in the cache; it just means that + # we only recently inserted it so it's only in the cache. If + # it's not in the cache either then we should end with a + # KeyError. del self.cache[key] else: + # Also make sure it's removed from the cache. try: del self.cache[key] except KeyError: pass + def iteritems(self): + for i,k in enumerate(self.keys()): + yield k, self[k] def sync(self): if self.cache: self.dict.update( (k, cPickle.dumps(v, self._protocol)) for k,v in self.cache.items() ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:08:36
|
Revision: 1446 http://assorted.svn.sourceforge.net/assorted/?rev=1446&view=rev Author: yangzhang Date: 2009-06-03 17:08:19 +0000 (Wed, 03 Jun 2009) Log Message: ----------- updated deps Modified Paths: -------------- mailing-list-filter/trunk/README Modified: mailing-list-filter/trunk/README =================================================================== --- mailing-list-filter/trunk/README 2009-06-03 17:07:53 UTC (rev 1445) +++ mailing-list-filter/trunk/README 2009-06-03 17:08:19 UTC (rev 1446) @@ -40,7 +40,6 @@ - [argparse](http://argparse.python-hosting.com/) 0.8.0 - [Python Commons](http://assorted.sf.net/python-commons/) 0.6 -- [path](http://www.jorendorff.com/articles/python/path/) 2.2 Install the program using the standard `setup.py` program. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 17:07:54
|
Revision: 1445 http://assorted.svn.sourceforge.net/assorted/?rev=1445&view=rev Author: yangzhang Date: 2009-06-03 17:07:53 +0000 (Wed, 03 Jun 2009) Log Message: ----------- using python commons path Modified Paths: -------------- mailing-list-filter/trunk/src/mlf.py Modified: mailing-list-filter/trunk/src/mlf.py =================================================================== --- mailing-list-filter/trunk/src/mlf.py 2009-06-03 00:17:16 UTC (rev 1444) +++ mailing-list-filter/trunk/src/mlf.py 2009-06-03 17:07:53 UTC (rev 1445) @@ -9,13 +9,13 @@ """ from __future__ import with_statement -from path import path from functools import partial from commons.log import * from contextlib import closing, contextmanager import getpass, logging, shelve, email, re, os, imaplib, itertools import argparse, collections, subprocess, shutil from commons import log, startup, seqs, networking, files, sqlhash +from commons.path import path info = partial(log.info, 'main') debug = partial(log.debug, 'main') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-03 01:22:24
|
Revision: 1444 http://assorted.svn.sourceforge.net/assorted/?rev=1444&view=rev Author: yangzhang Date: 2009-06-03 00:17:16 +0000 (Wed, 03 Jun 2009) Log Message: ----------- added faster incremental processing Modified Paths: -------------- mailing-list-filter/trunk/src/mlf.py Modified: mailing-list-filter/trunk/src/mlf.py =================================================================== --- mailing-list-filter/trunk/src/mlf.py 2009-06-02 10:02:44 UTC (rev 1443) +++ mailing-list-filter/trunk/src/mlf.py 2009-06-03 00:17:16 UTC (rev 1444) @@ -95,14 +95,14 @@ for row in chunk: yield row -def fetch_new_mail(cfg): +def fetch_new_mail(cfg, imap): if cfg.refresh: - try: os.remove(dbpath(cfg, 'mail')) + try: os.remove(dbpath(cfg, 'fetched')) except: pass - with closing(opendb(cfg, 'mail', 'w')) as mid2msg: + with closing(opendb(cfg, 'fetched', 'w')) as mid2msg: - minuid = mid2msg.get('maxuid', 1) + minuid = mid2msg.get('maxuid', 0) + 1 maxuid = getmaxuid(imap) # Every second item is just a closing paren. @@ -127,40 +127,39 @@ msg.uid = m.group('uid') msg.flags = m.group('flags').split() -# # Prepare a container for references to other msgs, and initialize the -# # thread ID. + # Prepare a container for references to other msgs, and initialize the + # thread ID. msg.refs = set() msg.tid = None # Add these to the map. if msg['Message-ID'] in mid2msg: - warning( 'duplicate message IDs:', - msg['Message-ID'], msg['Subject'] ) + log.warning( 'dups', 'duplicate message IDs:', + msg['Message-ID'], msg['Subject'] ) mid2msg[ msg['Message-ID'] ] = msg # Periodically sync to disk. if len(mid2msg.cache) > 1000: mid2msg.sync() mid2msg['maxuid'] = maxuid + # XXX + mid2msg['procuid'] = mid2msg['maxuid'] # # Function for analyzing messages. # -def iterpairs(mid2msg, midsrc): - for mid in midsrc: - yield mid, mid2msg[mid] - -def itermsgs(mid2msg, midsrc = None): - pairs = ( mid2msg.iteritems() - if midsrc is None else - iterpairs(mid2msg, midsrc) ) - for i, (mid, msg) in enumerate(pairs): - if mid != 'maxuid': yield msg - # Periodically sync to disk. - if mid2msg.cache is not None and len(mid2msg.cache) > 10000: - debug( 'syncing; now at i', i, 'mid', mid ) - mid2msg.sync() +def itermsgs(mid2msg, minuid, midsrc = None): + if midsrc is None: midsrc = mid2msg + special_keys = ['maxuid', 'procuid'] + for i, (mid, msg) in enumerate(midsrc.iteritems()): + if mid not in special_keys and msg.uid >= minuid: + if midsrc is mid2msg: yield msg + else: yield mid2msg[mid] + # Periodically sync to disk. + if mid2msg.cache is not None and len(mid2msg.cache) > 10000: + debug( 'syncing; now at i', i, 'mid', mid ) + mid2msg.sync() debug( 'syncing; finished after i', i, 'mid', mid ) mid2msg.sync() @@ -171,44 +170,43 @@ try: refmsg = mid2msg[refmid] except KeyError: - warning('no message with mid', refmid) + log.warning('badref', 'no message with mid', refmid) else: if refmsg.tid is None: thread_dfs(refmsg, tid, mid2msg) else: assert refmsg.tid == tid def mark_relevant_threads(cfg): -# shutil.copy(dbpath(cfg, 'fetched'), dbpath(cfg, 'bidir')) -# -# with closing(opendb(cfg, 'fetched')) as midsrc: -# with closing(opendb(cfg, 'bidir', 'w')) as mid2msg: -# info( 'maxuid', midsrc['maxuid'] ) -# info( 'constructing bidirectional ref graph' ) -# for msg in itermsgs(mid2msg, midsrc): -# debug('processing', msg['Message-ID']) -# # XXX -# if not hasattr(msg, 'refs'): msg.refs = set() -# if not hasattr(msg, 'tid'): msg.tid = None -# # XXX -# irt = msg.get_all('In-Reply-To', []) -# refs = msg.get_all('References', []) -# newrefs = ' '.join( irt + refs ).replace('><', '> <').split() -# msg.refs.update( newrefs ) -# -# # Connect nodes in graph bidirectionally. Ignore references to MIDs -# # that don't exist. -# for ref in newrefs: -# debug('adding', ref, '<->', msg['Message-ID']) -# try: mid2msg[ref].refs.add( msg['Message-ID'] ) -# except KeyError: warning( 'no message with mid', ref ) + shutil.copy(dbpath(cfg, 'fetched'), dbpath(cfg, 'bidir')) + with closing(opendb(cfg, 'fetched')) as midsrc: + with closing(opendb(cfg, 'bidir', 'w')) as mid2msg: + procuid = mid2msg.get('procuid', 0) + minuid = procuid + 1 + info( 'maxuid', midsrc['maxuid'], 'procuid', procuid ) + del procuid + info( 'constructing bidirectional ref graph' ) + for msg in itermsgs(mid2msg, minuid, midsrc): + debug('processing', msg['Message-ID']) + irt = msg.get_all('In-Reply-To', []) + refs = msg.get_all('References', []) + newrefs = ' '.join( irt + refs ).replace('><', '> <').split() + msg.refs.update( newrefs ) + + # Connect nodes in graph bidirectionally. Ignore references to MIDs + # that don't exist. + for ref in newrefs: + debug('adding', ref, '<->', msg['Message-ID']) + try: mid2msg[ref].refs.add( msg['Message-ID'] ) + except KeyError: log.warning( 'badref', 'no message with mid', ref ) + shutil.copy(dbpath(cfg, 'bidir'), dbpath(cfg, 'threaded')) with closing(opendb(cfg, 'bidir')) as midsrc: with closing(opendb(cfg, 'threaded', 'w')) as mid2msg: info( 'looking for relevant msgs (grouping them into threads)' ) tids = itertools.count() - for msg in itermsgs(mid2msg, midsrc): + for msg in itermsgs(mid2msg, minuid, midsrc): debug('threading', msg['Message-ID']) if ( msg.tid is None and ( cfg.sender in msg.get('From', '') or @@ -224,7 +222,7 @@ info( 'starring/unstarring relevant/irrelevant threads' ) - for msg in itermsgs(mid2msg): + for msg in itermsgs(mid2msg, 0): if msg.tid is not None: # is a relevant msgs if r'\Flagged' not in msg.flags: # not already flagged mark_unseen = not cfg.no_mark_unseen and r'\Seen' in msg.flags @@ -244,6 +242,8 @@ imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') if mark_seen: imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') + mid2msg['procuid'] = mid2msg['maxuid'] + # # Main function. # @@ -304,9 +304,9 @@ if not cfg.no_fetch: with login_imap(cfg) as imap: - fetch_new_mail(cfg) + fetch_new_mail(cfg, imap) - #mark_relevant_threads(cfg) + mark_relevant_threads(cfg) with login_imap(cfg) as imap: with closing(opendb(cfg, 'threaded')) as mid2msg: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-02 10:02:54
|
Revision: 1443 http://assorted.svn.sourceforge.net/assorted/?rev=1443&view=rev Author: yangzhang Date: 2009-06-02 10:02:44 +0000 (Tue, 02 Jun 2009) Log Message: ----------- rewrote MLF to be disk-based to handle large volumes of mail Modified Paths: -------------- mailing-list-filter/trunk/README mailing-list-filter/trunk/src/mlf.py Modified: mailing-list-filter/trunk/README =================================================================== --- mailing-list-filter/trunk/README 2009-06-01 21:11:41 UTC (rev 1442) +++ mailing-list-filter/trunk/README 2009-06-02 10:02:44 UTC (rev 1443) @@ -39,13 +39,13 @@ Requirements: - [argparse](http://argparse.python-hosting.com/) 0.8.0 -- [Python Commons](http://assorted.sf.net/python-commons/) 0.4 +- [Python Commons](http://assorted.sf.net/python-commons/) 0.6 - [path](http://www.jorendorff.com/articles/python/path/) 2.2 Install the program using the standard `setup.py` program. -Future Work Ideas ------------------ +Todo +---- - Currently, we assume that the server specification points to a mailbox containing all messages (both sent and received), and a message is determined Modified: mailing-list-filter/trunk/src/mlf.py =================================================================== --- mailing-list-filter/trunk/src/mlf.py 2009-06-01 21:11:41 UTC (rev 1442) +++ mailing-list-filter/trunk/src/mlf.py 2009-06-02 10:02:44 UTC (rev 1443) @@ -12,8 +12,9 @@ from path import path from functools import partial from commons.log import * -from contextlib import closing -import getpass, logging, shelve, email, re, os, imaplib, itertools, argparse, collections +from contextlib import closing, contextmanager +import getpass, logging, shelve, email, re, os, imaplib, itertools +import argparse, collections, subprocess, shutil from commons import log, startup, seqs, networking, files, sqlhash info = partial(log.info, 'main') @@ -23,21 +24,40 @@ die = partial(log.die, 'main') exception = partial(log.exception, 'main') -def opendb(dbpath): - return sqlhash.Shelf(sqlhash.SQLhash(dbpath, flags = 'w'), - protocol = 2, writeback = True) +# +# Functions for getting local file paths and opening them. +# -def thread_dfs(msg, tid, mid2msg, tid2msgs): - assert msg.tid is None - msg.tid = tid - tid2msgs[tid].append(msg) - for refmid in msg.refs: - refmsg = mid2msg[refmid] - if refmsg.tid is None: - thread_dfs(refmsg, tid, mid2msg, tid2msgs) - else: - assert refmsg.tid == tid +def dbpath(cfg, suffix): + return ( cfg.cachedir / + files.cleanse_filename(cfg.sender) + '-' + suffix ) +def opendb(cfg, suffix, flags = 'r'): + return sqlhash.Shelf(sqlhash.SQLhash(dbpath(cfg, suffix), + flags = flags), + protocol = 2, + writeback = flags == 'w', + cache = flags == 'w') + +# +# Functions for working with the server. +# + +@contextmanager +def login_imap(cfg): + info('connecting and logging in') + with networking.logout(imaplib.IMAP4_SSL(cfg.host, cfg.port)) as imap: + imap.login(cfg.user, cfg.passwd) + # Close is only valid in the authenticated state. + with closing(imap) as imap: + info('selecting mailbox') + imap.select(cfg.mailbox) + yield imap + +# +# Functions for fetching messages from the server. +# + def getmaxuid(imap): info( 'finding max UID' ) # We use UIDs rather than the default of sequence numbers because UIDs are @@ -49,7 +69,7 @@ del uids return maxuid -def getmail(imap, minuid, maxuid): +def fetch_range(imap, minuid, maxuid): info( 'fetching messages', minuid, 'to', maxuid ) # The syntax/fields of the FETCH command is documented in RFC 2060. Also, # this article contains a brief overview: @@ -75,6 +95,159 @@ for row in chunk: yield row +def fetch_new_mail(cfg): + if cfg.refresh: + try: os.remove(dbpath(cfg, 'mail')) + except: pass + + with closing(opendb(cfg, 'mail', 'w')) as mid2msg: + + minuid = mid2msg.get('maxuid', 1) + maxuid = getmaxuid(imap) + + # Every second item is just a closing paren. + # Example data: + # [('13300 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {67}', + # 'Message-ID: <mai...@py...>\r\n\r\n'), + # ')', + # ('13301 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {59}', + # 'Message-Id: <200...@hv...>\r\n\r\n'), + # ')', + # ('13302 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {92}', + # 'Message-ID: <C43EAFC0.2E3AE%ni...@ya...>\r\nIn-Reply-To: <481...@gm...>\r\n\r\n')] + pat = re.compile(r"(?P<seqno>\d+) \(UID (?P<uid>\d+) FLAGS \((?P<flags>[^)]+)\)") + for i, ((envelope, data), paren) in enumerate(seqs.grouper(2, fetch_range(imap, minuid, maxuid))): + # Parse the body. + msg = email.message_from_string(data) + + # Parse the envelope. + m = pat.match(envelope) + if m is None: raise Exception('envelope: %r' % envelope) + msg.seqno = m.group('seqno') + msg.uid = m.group('uid') + msg.flags = m.group('flags').split() + +# # Prepare a container for references to other msgs, and initialize the +# # thread ID. + msg.refs = set() + msg.tid = None + + # Add these to the map. + if msg['Message-ID'] in mid2msg: + warning( 'duplicate message IDs:', + msg['Message-ID'], msg['Subject'] ) + mid2msg[ msg['Message-ID'] ] = msg + + # Periodically sync to disk. + if len(mid2msg.cache) > 1000: mid2msg.sync() + + mid2msg['maxuid'] = maxuid + +# +# Function for analyzing messages. +# + +def iterpairs(mid2msg, midsrc): + for mid in midsrc: + yield mid, mid2msg[mid] + +def itermsgs(mid2msg, midsrc = None): + pairs = ( mid2msg.iteritems() + if midsrc is None else + iterpairs(mid2msg, midsrc) ) + for i, (mid, msg) in enumerate(pairs): + if mid != 'maxuid': yield msg + # Periodically sync to disk. + if mid2msg.cache is not None and len(mid2msg.cache) > 10000: + debug( 'syncing; now at i', i, 'mid', mid ) + mid2msg.sync() + debug( 'syncing; finished after i', i, 'mid', mid ) + mid2msg.sync() + +def thread_dfs(msg, tid, mid2msg): + assert msg.tid is None + msg.tid = tid + for refmid in msg.refs: + try: + refmsg = mid2msg[refmid] + except KeyError: + warning('no message with mid', refmid) + else: + if refmsg.tid is None: thread_dfs(refmsg, tid, mid2msg) + else: assert refmsg.tid == tid + +def mark_relevant_threads(cfg): + +# shutil.copy(dbpath(cfg, 'fetched'), dbpath(cfg, 'bidir')) +# +# with closing(opendb(cfg, 'fetched')) as midsrc: +# with closing(opendb(cfg, 'bidir', 'w')) as mid2msg: +# info( 'maxuid', midsrc['maxuid'] ) +# info( 'constructing bidirectional ref graph' ) +# for msg in itermsgs(mid2msg, midsrc): +# debug('processing', msg['Message-ID']) +# # XXX +# if not hasattr(msg, 'refs'): msg.refs = set() +# if not hasattr(msg, 'tid'): msg.tid = None +# # XXX +# irt = msg.get_all('In-Reply-To', []) +# refs = msg.get_all('References', []) +# newrefs = ' '.join( irt + refs ).replace('><', '> <').split() +# msg.refs.update( newrefs ) +# +# # Connect nodes in graph bidirectionally. Ignore references to MIDs +# # that don't exist. +# for ref in newrefs: +# debug('adding', ref, '<->', msg['Message-ID']) +# try: mid2msg[ref].refs.add( msg['Message-ID'] ) +# except KeyError: warning( 'no message with mid', ref ) + + shutil.copy(dbpath(cfg, 'bidir'), dbpath(cfg, 'threaded')) + + with closing(opendb(cfg, 'bidir')) as midsrc: + with closing(opendb(cfg, 'threaded', 'w')) as mid2msg: + info( 'looking for relevant msgs (grouping them into threads)' ) + tids = itertools.count() + for msg in itermsgs(mid2msg, midsrc): + debug('threading', msg['Message-ID']) + if ( msg.tid is None and + ( cfg.sender in msg.get('From', '') or + cfg.sender in msg.get('To', '') or + cfg.sender in msg.get('Cc', '') ) ): + thread_dfs(msg, tids.next(), mid2msg) + +# +# Functions for storing metadata changes back to the server. +# + +def flag_relevant_msgs(cfg, imap, mid2msg): + + info( 'starring/unstarring relevant/irrelevant threads' ) + + for msg in itermsgs(mid2msg): + if msg.tid is not None: # is a relevant msgs + if r'\Flagged' not in msg.flags: # not already flagged + mark_unseen = not cfg.no_mark_unseen and r'\Seen' in msg.flags + log.info( 'star', '\n', + 'star' + (' and mark unseen' if mark_unseen else ''), + msg ) + if not cfg.pretend: + imap.uid('STORE', msg.uid, '+FLAGS', r'\Flagged') + if mark_unseen: imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') + else: # is not a relevant msg + if r'\Flagged' in msg.flags: # was inadvertently flagged + mark_seen = not cfg.no_mark_seen and r'\Seen' not in msg.flags + log.info( 'unstar', '\n', + 'unstar' + (' and mark seen' if mark_seen else ''), + msg ) + if not cfg.pretend: + imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') + if mark_seen: imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') + +# +# Main function. +# + def main(argv): p = argparse.ArgumentParser(description = __doc__) p.add_argument('--credfile', default = path( '~/.mlf.auth' ).expanduser(), @@ -129,131 +302,14 @@ files.soft_makedirs(cfg.cachedir) - info('connecting and logging in') + if not cfg.no_fetch: + with login_imap(cfg) as imap: + fetch_new_mail(cfg) - if True: - ###with networking.logout(imaplib.IMAP4_SSL(cfg.host, cfg.port)) as imap: - ###imap.login(cfg.user, cfg.passwd) - # Close is only valid in the authenticated state. - ###with closing(imap) as imap: + #mark_relevant_threads(cfg) - info('selecting mailbox') - ###imap.select(cfg.mailbox) + with login_imap(cfg) as imap: + with closing(opendb(cfg, 'threaded')) as mid2msg: + flag_relevant_msgs(cfg, imap, mid2msg) - dbpath = cfg.cachedir / files.cleanse_filename(cfg.sender) - - # - # Fetch message IDs, references, and senders into persistent store. - # - - if cfg.refresh: - try: os.remove(dbpath) - except: pass - - if not cfg.no_fetch: - with closing(opendb(dbpath)) as mid2msg: - - minuid = mid2msg.get('maxuid', 1) - maxuid = getmaxuid(imap) - - # Every second item is just a closing paren. - # Example data: - # [('13300 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {67}', - # 'Message-ID: <mai...@py...>\r\n\r\n'), - # ')', - # ('13301 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {59}', - # 'Message-Id: <200...@hv...>\r\n\r\n'), - # ')', - # ('13302 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {92}', - # 'Message-ID: <C43EAFC0.2E3AE%ni...@ya...>\r\nIn-Reply-To: <481...@gm...>\r\n\r\n')] - pat = re.compile(r"(?P<seqno>\d+) \(UID (?P<uid>\d+) FLAGS \((?P<flags>[^)]+)\)") - for i, ((envelope, data), paren) in enumerate(seqs.grouper(2, getmail(imap, minuid, maxuid))): - # Parse the body. - msg = email.message_from_string(data) - - # Parse the envelope. - m = pat.match(envelope) - if m is None: raise Exception('envelope: %r' % envelope) - msg.seqno = m.group('seqno') - msg.uid = m.group('uid') - msg.flags = m.group('flags').split() - - # Prepare a container for references to other msgs, and initialize the - # thread ID. - msg.refs = set() - msg.tid = None - - # Add these to the map. - if msg['Message-ID'] in mid2msg: - log.warning( 'dups', 'duplicate message IDs:', - msg['Message-ID'], msg['Subject'] ) - mid2msg[ msg['Message-ID'] ] = msg - - # Periodically sync to disk. - if len(mid2msg.cache) > 1000: mid2msg.sync() - - mid2msg['maxuid'] = maxuid - - with closing(opendb(dbpath)) as mid2msg: - - info( 'maxuid', mid2msg['maxuid'] ) - - info( 'constructing undirected graph' ) - - for i, (mid, msg) in enumerate(mid2msg.iteritems()): - # Extract any references. - irt = msg.get_all('In-Reply-To', []) - refs = msg.get_all('References', []) - msg.refs.update( ' '.join( irt + refs ).replace('><', '> <').split() ) - - # Connect nodes in graph bidirectionally. Ignore references to MIDs - # that don't exist. - for ref in msg.refs: - try: mid2msg[ref].refs.add(msg['Message-ID']) - except KeyError: log.warning( 'no message with id', ref ) - - # Periodically sync to disk. - if len(mid2msg.cache) > 10000: - info( 'syncing; now at', i ) - mid2msg.sync() - - info('looking for relevant (grouping the messages into threads)') - - # Look for messages sent by us or addressed to us, and add their - # connected components into tid2msgs. - tids = itertools.count() - tid2msgs = collections.defaultdict(list) - for mid, msg in mid2msg.iteritems(): - if ( cfg.sender in msg.get('From', '' ) or - cfg.sender in msg.get('To', '' ) or - cfg.sender in msg.get('Cc', '' ) ): - thread_dfs(msg, tids.next(), mid2msg, tid2msgs) - - info( 'starring the relevant threads, in which I am a participant' ) - - rel_tids = set() - for srcmsg in srcs: - if srcmsg.tid not in rel_tids: - rel_tids.add(srcmsg.tid) - for msg in tid2msgs[srcmsg.tid]: - if r'\Flagged' not in msg.flags: - log.info( 'star', '\n', msg ) - if not cfg.pretend: - imap.uid('STORE', msg.uid, '+FLAGS', r'\Flagged') - if not cfg.no_mark_unseen and r'\Seen' in msg.flags: - imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') - - info( 'unstarring irrelevant threads, in which I am not a participant' ) - - all_tids = set( tid2msgs.iterkeys() ) - irrel_tids = all_tids - rel_tids - for tid in irrel_tids: - for msg in tid2msgs[tid]: - if r'\Flagged' in msg.flags: - log.info( 'unstar', '\n', msg ) - if not cfg.pretend: - imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') - if not cfg.no_mark_seen and r'\Seen' not in msg.flags: - imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') - startup.run_main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-06-01 21:12:02
|
Revision: 1442 http://assorted.svn.sourceforge.net/assorted/?rev=1442&view=rev Author: yangzhang Date: 2009-06-01 21:11:41 +0000 (Mon, 01 Jun 2009) Log Message: ----------- fixed duplicity args Modified Paths: -------------- configs/trunk/src/cron/backup.bash Modified: configs/trunk/src/cron/backup.bash =================================================================== --- configs/trunk/src/cron/backup.bash 2009-05-31 20:26:48 UTC (rev 1441) +++ configs/trunk/src/cron/backup.bash 2009-06-01 21:11:41 UTC (rev 1442) @@ -3,10 +3,12 @@ FORCE_BASHRC=1 . ~/.bashrc && . common.bash || exit 1 if [[ "$( date +%d )" == 01 ]] -then args=--full +then args=full else args= fi +args="$args -vINFO" + src=~/.gnome2/f-spot/photos.db dst=~/personal/backups/f-spot/photos.db if [ -f "$src" ] && ( ! [ -f "$dst" ] || ! diff -q "$src" "$dst" ) then mkdir -p "$( dirname "$dst" )" ; cp "$src" "$dst" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-31 20:27:01
|
Revision: 1441 http://assorted.svn.sourceforge.net/assorted/?rev=1441&view=rev Author: yangzhang Date: 2009-05-31 20:26:48 +0000 (Sun, 31 May 2009) Log Message: ----------- - removed logo border - fixed contrib listing bug - better invalid key error Modified Paths: -------------- pitch-in/trunk/src/pitchin/pitchin/templates/main.html pitch-in/trunk/src/pitchin/pitchin/views.py pitch-in/trunk/src/pitchin/static/default.css Modified: pitch-in/trunk/src/pitchin/pitchin/templates/main.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-31 20:25:25 UTC (rev 1440) +++ pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-31 20:26:48 UTC (rev 1441) @@ -1,5 +1,6 @@ {% extends 'base.html' %} {% block body %} + <p class="error">{{generror}}</p> <p class="line">Easily create and manage a money pool that others can contribute to.</p> <p> To create a pool, just enter a description of what it's for here, and you Modified: pitch-in/trunk/src/pitchin/pitchin/views.py =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-31 20:25:25 UTC (rev 1440) +++ pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-31 20:26:48 UTC (rev 1441) @@ -4,13 +4,17 @@ from pitchin.models import Pool import cPickle, cgi -def getPool(request): return db.get(db.Key(request.REQUEST['key'])) +class invalid_pool(Exception): pass +def getPool(request): + try: return db.get(db.Key(request.REQUEST['key'])) + except: raise invalid_pool() + def getContribs(pool): return cPickle.loads(str(pool.contribs)) def serContribs(contribs): return cPickle.dumps(contribs, 2) def aggContribs(contribs): if len(contribs) == 0: - return '' + return [] else: return [('Max total', sum(contribs.itervalues())), ('If everyone paid the minimum', len(contribs) * min(contribs.itervalues()))] @@ -40,13 +44,16 @@ def view(request, **params): if 'key' not in request.REQUEST: return HttpResponseRedirect('/') - pool = getPool(request) - return render_to_response('pool.html', - dict(descrip = pool.descrip, - contribs = getContribs(pool), - aggcontribs = aggContribs(getContribs(pool)), - key = request.REQUEST['key'], - **params)) + try: + pool = getPool(request) + return render_to_response('pool.html', + dict(descrip = pool.descrip, + contribs = getContribs(pool).iteritems(), + aggcontribs = aggContribs(getContribs(pool)), + key = request.REQUEST['key'], + **params)) + except invalid_pool: + return bad_pool(request) def update(request): try: @@ -57,12 +64,19 @@ except invalid_submit, ex: return view(request, error = ex, name = request.REQUEST['name'], amount = request.REQUEST['amount']) else: - pool = getPool(request) - contribs = getContribs(pool) - contribs[request.REQUEST['name']] = amount - pool.contribs = cPickle.dumps(contribs) - pool.put() - return HttpResponseRedirect('/pool?key=%s' % pool.key()) + try: + pool = getPool(request) + except invalid_pool: + return bad_pool(request) + else: + contribs = getContribs(pool) + contribs[request.REQUEST['name']] = amount + pool.contribs = cPickle.dumps(contribs) + pool.put() + return HttpResponseRedirect('/pool?key=%s' % pool.key()) def sponsorship(request): return render_to_response('sponsorship.html') + +def bad_pool(request): + return render_to_response('main.html', dict(generror = 'Pool not found/invalid pool ID')) Modified: pitch-in/trunk/src/pitchin/static/default.css =================================================================== --- pitch-in/trunk/src/pitchin/static/default.css 2009-05-31 20:25:25 UTC (rev 1440) +++ pitch-in/trunk/src/pitchin/static/default.css 2009-05-31 20:26:48 UTC (rev 1441) @@ -32,3 +32,4 @@ a:link { color: #55aaff; text-decoration: none; } a:visited { color: #55aaff; text-decoration: none; } a:hover { color: #ff3399; } +a img { border-width: 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-31 20:25:37
|
Revision: 1440 http://assorted.svn.sourceforge.net/assorted/?rev=1440&view=rev Author: yangzhang Date: 2009-05-31 20:25:25 +0000 (Sun, 31 May 2009) Log Message: ----------- added pitch-in Modified Paths: -------------- assorted-site/trunk/index.txt Modified: assorted-site/trunk/index.txt =================================================================== --- assorted-site/trunk/index.txt 2009-05-31 20:08:24 UTC (rev 1439) +++ assorted-site/trunk/index.txt 2009-05-31 20:25:25 UTC (rev 1440) @@ -98,6 +98,8 @@ - Sandbox: heap of small test cases to explore (mostly programming language details, bugs, corner cases, features, etc.) (passive) - Miscellaneous + - [PitchIn](pitch-in): a simple web application for collaboratively managing + a money pool (active) - [Music Labeler](music-labeler): a slick GUI for quickly labeling/categorizing music (passive) - [Mailing List Filter](mailing-list-filter): deal with high-volume mailing This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-31 20:08:29
|
Revision: 1439 http://assorted.svn.sourceforge.net/assorted/?rev=1439&view=rev Author: yangzhang Date: 2009-05-31 20:08:24 +0000 (Sun, 31 May 2009) Log Message: ----------- forgot to add sponsorship page Added Paths: ----------- pitch-in/trunk/src/pitchin/pitchin/templates/sponsorship.html Added: pitch-in/trunk/src/pitchin/pitchin/templates/sponsorship.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/sponsorship.html (rev 0) +++ pitch-in/trunk/src/pitchin/pitchin/templates/sponsorship.html 2009-05-31 20:08:24 UTC (rev 1439) @@ -0,0 +1,5 @@ +{% extends 'base.html' %} +{% block body %} +<p class="line">Interested in sponsoring PitchIn?</p> +<p>Get in touch with us by emailing <a href="mailto:in...@yz...">in...@yz...</a>.</p> +{% endblock %} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-31 20:08:01
|
Revision: 1438 http://assorted.svn.sourceforge.net/assorted/?rev=1438&view=rev Author: yangzhang Date: 2009-05-31 20:07:57 +0000 (Sun, 31 May 2009) Log Message: ----------- - added publisher - resized logo - style tweaks - refactored views, esp listing of contribs - added hidden sponsorship view - converted to valid xhtml - filled out the README Modified Paths: -------------- pitch-in/trunk/README pitch-in/trunk/src/pitchin/pitchin/templates/base.html pitch-in/trunk/src/pitchin/pitchin/templates/main.html pitch-in/trunk/src/pitchin/pitchin/templates/pool.html pitch-in/trunk/src/pitchin/pitchin/urls.py pitch-in/trunk/src/pitchin/pitchin/views.py pitch-in/trunk/src/pitchin/static/default.css pitch-in/trunk/src/pitchin/static/pitchin.png Added Paths: ----------- pitch-in/trunk/publish.bash Modified: pitch-in/trunk/README =================================================================== --- pitch-in/trunk/README 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/README 2009-05-31 20:07:57 UTC (rev 1438) @@ -1,5 +1,37 @@ -Nice new features in Django 1.0: +Overview +-------- -- new cycle syntax: cycle '0' '1' -- autoescape -- for key, value in collection +PitchIn is a simple web application for collaboratively managing a money pool. +The service runs on [Google App Engine] at <http://pitch-in.appspot.com/>. + +Requirements +------------ + +- [Django] 0.96 +- [Google App Engine] + +[Django]: http://www.djangoproject.com/ +[Google App Engine]: http://code.google.com/appengine/ + +Resources +--------- + +These are some other resources I used in the creation of this website: + +- [RoundedCornr](http://www.roundedcornr.com/) +- [Web 2.0 Logo Creator](http://creatr.cc/creatr/) + +Todo +---- + +- Disallow updates +- Email notification +- Administration link for removes, updates, de-anonymizing +- Anonymous participants (visible only to administration) +- Other types of pools besides integers (decimals, unique strings, strings) +- Comprehensive logging +- Archiving/garbage collection +- Upgrade to Django 1.0. Nice new features in Django 1.0 include: + - new cycle syntax: cycle '0' '1' + - autoescape + - for key, value in collection Copied: pitch-in/trunk/publish.bash (from rev 1424, clamp/trunk/publish.bash) =================================================================== --- pitch-in/trunk/publish.bash (rev 0) +++ pitch-in/trunk/publish.bash 2009-05-31 20:07:57 UTC (rev 1438) @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +fullname='PitchIn' +version=1.0 +license=agpl3 +websrcs=( README ) +rels=( src-tgz: ) +nodl=true +. assorted.bash "$@" Modified: pitch-in/trunk/src/pitchin/pitchin/templates/base.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/base.html 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/pitchin/templates/base.html 2009-05-31 20:07:57 UTC (rev 1438) @@ -1,5 +1,8 @@ -<html> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>{% block title %}PitchIn{% endblock %}</title> <link rel="stylesheet" type="text/css" href="static/default.css"/> </head> @@ -7,13 +10,29 @@ <div class="box"> <div class="boxtop"><div></div></div> <div class="header"> - <img src="static/pitchin.png"/> + <a href="/"><img src="static/pitchin.png" alt="PitchIn logo"/></a> </div> <div class="body"> {% block body %}{% endblock %} - <small>PitchIn © 2009 <a href="http://www.mit.edu/~y_z/">Yang Zhang</a></small> + <div style="margin-top: 50px"> + <small> + <strong>PitchIn</strong> © 2009 <a href="http://www.mit.edu/~y_z/">YZ</a> | + <a href="http://assorted.sf.net/pitch-in/">AGPL Source</a> <!--| + <a href="sponsorship">Sponsorship</a>--> + </small> + </div> </div> <div class="boxbottom"><div></div></div> </div> + <script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); + </script> + <script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-7136318-2"); + pageTracker._trackPageview(); + } catch(err) {} + </script> </body> </html> Modified: pitch-in/trunk/src/pitchin/pitchin/templates/main.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-31 20:07:57 UTC (rev 1438) @@ -10,7 +10,7 @@ <form action="/create" method="post"> <div> <input class="text-input" type="text" name="descrip"/> - <input type="submit" width="50" value="Create Pool"> + <input type="submit" value="Create Pool"/> </div> </form> <div class="example"> Modified: pitch-in/trunk/src/pitchin/pitchin/templates/pool.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-31 20:07:57 UTC (rev 1438) @@ -1,27 +1,37 @@ {% extends 'base.html' %} {% block body %} <p style="font-size: larger"><span style="font-weight: bold">Pool:</span> {{descrip|escape}}</p> - {% for contrib in contribs %} - <div class="row{% cycle 0,1 %}">{{contrib.0|escape}}: {{contrib.1|escape}}</div> - {% endfor %} - {% for contrib in aggcontribs %} - <div class="aggrow">{{contrib.0|escape}}: {{contrib.1|escape}}</div> - {% endfor %} + {% if not contribs %} + <p style="font-style: italic;">(no participants yet)</p> + {% else %} + {% for contrib in contribs %} + <div class="row{% cycle 0,1 %}">{{contrib.0|escape}}: {{contrib.1|escape}}</div> + {% endfor %} + {% for contrib in aggcontribs %} + <div class="aggrow">{{contrib.0|escape}}: {{contrib.1|escape}}</div> + {% endfor %} + {% endif %} <p> To add or update your own contribution to the pool, enter the following information. </p> <form action="/pool" method="post"> <p class="error">{{error}}</p> - <input type="hidden" name="key" value="{{key|urlencode}}"/> <div> - <label name="name">Name:</label> - <input type="text" name="name"/> + <input type="hidden" name="key" value="{{key|urlencode}}"/> </div> <div> - <label name="amount">Contribution:</label> - <input type="text" name="amount"/> + <label> + Name: + <input type="text" name="name" value="{{name|escape}}"/> + </label> </div> + <div> + <label> + Contribution: + <input type="text" name="amount" value="{{amount|escape}}"/> + </label> + </div> <div><input type="submit" value="Enter the pool!"/></div> </form> {% endblock %} Modified: pitch-in/trunk/src/pitchin/pitchin/urls.py =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/urls.py 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/pitchin/urls.py 2009-05-31 20:07:57 UTC (rev 1438) @@ -8,6 +8,7 @@ (r'^$', 'pitchin.views.main'), (r'^create$', 'pitchin.views.create'), (r'^pool$', 'pitchin.views.pool'), + (r'^sponsorship$', 'pitchin.views.sponsorship'), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: Modified: pitch-in/trunk/src/pitchin/pitchin/views.py =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-31 20:07:57 UTC (rev 1438) @@ -8,20 +8,12 @@ def getContribs(pool): return cPickle.loads(str(pool.contribs)) def serContribs(contribs): return cPickle.dumps(contribs, 2) -def showContribs(pool): - contribs = getContribs(pool) +def aggContribs(contribs): if len(contribs) == 0: - return '<p style="font-style: italic;">(no participants yet)</p>' + return '' else: - return contribs.items() , [('Max total', sum(contribs.itervalues())), - ('If everyone paid the minimum', len(contribs) * min(contribs.itervalues()))] - s = '<div class="rows">' - for i, (name, amount) in enumerate(contribs.iteritems()): - s += '<div class="row%d">%s: %d</div>' % (i % 2, cgi.escape(name), amount) - s += '<div class="aggrow">Max total: %d</div>' % (sum(contribs.itervalues()),) - s += '<div class="aggrow">If everyone paid the minimum: %d</div>' % (len(contribs) * min(contribs.itervalues()),) - s += '</div>' - return s + return [('Max total', sum(contribs.itervalues())), + ('If everyone paid the minimum', len(contribs) * min(contribs.itervalues()))] class invalid_submit(Exception): pass def validate(pred, msg): @@ -34,7 +26,9 @@ def create(request): if request.REQUEST['descrip'].strip() == '': - return render_to_response('main.html', {'error': 'Must specify a description'}) + return render_to_response('main.html', + dict(error = 'Must specify a description', + descrip = request.REQUEST['descrip'])) pool = Pool(descrip = request.REQUEST['descrip'], contribs = cPickle.dumps({})) pool.put() return render_to_response('created.html', {'key': pool.key()}) @@ -43,14 +37,16 @@ if request.method == 'GET': return view(request) else: return update(request) -def view(request, error = ''): +def view(request, **params): + if 'key' not in request.REQUEST: + return HttpResponseRedirect('/') pool = getPool(request) return render_to_response('pool.html', - dict(error = error, - descrip = pool.descrip, - contribs = showContribs(pool)[0], - aggcontribs = showContribs(pool)[1], - key = request.REQUEST['key'])) + dict(descrip = pool.descrip, + contribs = getContribs(pool), + aggcontribs = aggContribs(getContribs(pool)), + key = request.REQUEST['key'], + **params)) def update(request): try: @@ -59,7 +55,7 @@ try: amount = int(request.REQUEST['amount']) except ValueError: raise invalid_submit('You must enter an integer dollar amount.') except invalid_submit, ex: - return view(request, error = ex) + return view(request, error = ex, name = request.REQUEST['name'], amount = request.REQUEST['amount']) else: pool = getPool(request) contribs = getContribs(pool) @@ -67,3 +63,6 @@ pool.contribs = cPickle.dumps(contribs) pool.put() return HttpResponseRedirect('/pool?key=%s' % pool.key()) + +def sponsorship(request): + return render_to_response('sponsorship.html') Modified: pitch-in/trunk/src/pitchin/static/default.css =================================================================== --- pitch-in/trunk/src/pitchin/static/default.css 2009-05-28 16:56:05 UTC (rev 1437) +++ pitch-in/trunk/src/pitchin/static/default.css 2009-05-31 20:07:57 UTC (rev 1438) @@ -8,7 +8,7 @@ .header { text-align: center; width: 100%; } .body { margin: 0 30px; text-align: center; } .error { color: red; } -.example { background-color: #ffffcc; } +.example { background-color: #ffffcc; margin: 50px 0; padding: 10px 0; } .boxbottom div { background: url(bl.png) no-repeat bottom left; } .boxbottom { background: url(br.png) no-repeat bottom right; } label, input { @@ -23,9 +23,12 @@ } .text-input { width: 75%; } .quote { font-family: serif; font-size: 50pt; float: left; } -.line { width: 75%; font-size: larger; font-style: italic; margin: 0 auto; } +.line { width: 75%; font-size: larger; font-style: italic; margin: 0 auto; margin-bottom: 50px; } .rows { width: 75%; margin: 0 auto; } .row0, .row1, .aggrow { padding-top: 3px; padding-bottom: 3px; } -.row0 { background-color: #dddddd; } -.row1 { background-color: #eeeeee; } +.row0 { background-color: #e3e3f8; } +.row1 { background-color: #eeeeff; } .aggrow { font-weight: bold; } +a:link { color: #55aaff; text-decoration: none; } +a:visited { color: #55aaff; text-decoration: none; } +a:hover { color: #ff3399; } Modified: pitch-in/trunk/src/pitchin/static/pitchin.png =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-28 16:56:16
|
Revision: 1437 http://assorted.svn.sourceforge.net/assorted/?rev=1437&view=rev Author: yangzhang Date: 2009-05-28 16:56:05 +0000 (Thu, 28 May 2009) Log Message: ----------- fixed setup issues at yahoo Modified Paths: -------------- configs/trunk/bootstrap.bash shell-tools/trunk/src/bash-commons/common.bash Modified: configs/trunk/bootstrap.bash =================================================================== --- configs/trunk/bootstrap.bash 2009-05-25 18:41:11 UTC (rev 1436) +++ configs/trunk/bootstrap.bash 2009-05-28 16:56:05 UTC (rev 1437) @@ -9,6 +9,7 @@ set -o nounset set -o errexit +set -x setup_coreutils= @@ -34,11 +35,12 @@ } pkg_install() { - if type apt-get ; then + if type apt-get 2> /dev/null ; then sudo apt-get install -y "$@" - elif type yum ; then + elif type yum 2> /dev/null ; then sudo yum install -y "$@" else + echo 'requires apt-get or yum' return 1 fi } @@ -78,7 +80,7 @@ type cat type svn type perl -type gcc || use_sudo && pkg_install build-essential +type gcc || { use_sudo && pkg_install build-essential ; } type python if type wget ; then fetch() { wget -O- "$@" ; } Modified: shell-tools/trunk/src/bash-commons/common.bash =================================================================== --- shell-tools/trunk/src/bash-commons/common.bash 2009-05-25 18:41:11 UTC (rev 1436) +++ shell-tools/trunk/src/bash-commons/common.bash 2009-05-28 16:56:05 UTC (rev 1437) @@ -505,13 +505,13 @@ refresh-local() { ( mkdir -p "$USER_PREFIX" && cd "$USER_PKG" && - stow -t "$USER_PREFIX" "$@" * ) + stow -t "$USER_PREFIX" !(armed) ) } refresh-opt() { ( sudo -u pkg mkdir -p "$GLOBAL_PREFIX" && cd "$GLOBAL_PKG" && - sudo -u pkg stow -t "$GLOBAL_PREFIX" "$@" !(armed) ) + sudo -u pkg stow -t "$GLOBAL_PREFIX" !(armed) ) } cabal-install-all() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 18:41:28
|
Revision: 1436 http://assorted.svn.sourceforge.net/assorted/?rev=1436&view=rev Author: yangzhang Date: 2009-05-25 18:41:11 +0000 (Mon, 25 May 2009) Log Message: ----------- reformatted the grammar Modified Paths: -------------- clamp/trunk/README Modified: clamp/trunk/README =================================================================== --- clamp/trunk/README 2009-05-25 18:34:15 UTC (rev 1435) +++ clamp/trunk/README 2009-05-25 18:41:11 UTC (rev 1436) @@ -193,37 +193,39 @@ recognises more or less the following grammar: <pre> - _lambda-expression_: - _lambda-decl_ _lambda-body~opt~_ +_lambda-expression_: + _lambda-decl_ _lambda-body~opt~_ - _lambda-decl_: - `lambda` _return-type~opt~_ _param-list~opt~_ _param-list_ +_lambda-decl_: + `lambda` _return-type~opt~_ _param-list~opt~_ _param-list_ - _return-type_: - _type-id_ +_return-type_: + _type-id_ - _param-list_: - ( ) - ( _parameter_ ) - ( _parameter_ , ... ) +_param-list_: + ( ) | + ( _parameter_ ) | + ( _parameter_ , ... ) - parameter: - _type-id_ _identifier~opt~_ _initialiser~opt~_ +parameter: + _type-id_ _identifier~opt~_ _initialiser~opt~_ - initialiser: - = _expression_ +initialiser: + = _expression_ - lambda-body: - { _statement~opt~_ ... } +lambda-body: + { _statement~opt~_ ... } </pre> where _statement_ represents any valid C++ statement, possibly making use of the following extended expressions: - _extended-expression_: - _lambda-expression_ - `__ctx` ( _expression_ ) - `__ref` ( _expression_ ) +<pre> +_extended-expression_: + _lambda-expression_ | + `__ctx` ( _expression_ ) | + `__ref` ( _expression_ ) +</pre> Portability ----------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 18:34:26
|
Revision: 1435 http://assorted.svn.sourceforge.net/assorted/?rev=1435&view=rev Author: yangzhang Date: 2009-05-25 18:34:15 +0000 (Mon, 25 May 2009) Log Message: ----------- removed unnecessary vnc forwarding Modified Paths: -------------- configs/trunk/src/ssh/config Modified: configs/trunk/src/ssh/config =================================================================== --- configs/trunk/src/ssh/config 2009-05-25 18:32:50 UTC (rev 1434) +++ configs/trunk/src/ssh/config 2009-05-25 18:34:15 UTC (rev 1435) @@ -141,7 +141,6 @@ Host zs HostName zs.ath.cx User yang - LocalForward 5901 localhost:5900 ForwardX11 yes # Rohan K @@ -174,7 +173,6 @@ HostName harvard.csail.mit.edu User yang ForwardX11 yes - LocalForward 5902 localhost:5900 Host cs HostName login.csail.mit.edu @@ -200,7 +198,6 @@ Host home HostName zs.ath.cx User yang - LocalForward 5901 localhost:5900 ForwardX11 yes Host ocf This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 18:33:03
|
Revision: 1434 http://assorted.svn.sourceforge.net/assorted/?rev=1434&view=rev Author: yangzhang Date: 2009-05-25 18:32:50 +0000 (Mon, 25 May 2009) Log Message: ----------- tweaked cpbkup; refactored symlink-tree into cp-tree-skel, op-tree-files, cp-tree, symlink-tree; added printable-slides Modified Paths: -------------- shell-tools/trunk/src/bash-commons/common.bash Modified: shell-tools/trunk/src/bash-commons/common.bash =================================================================== --- shell-tools/trunk/src/bash-commons/common.bash 2009-05-25 18:31:33 UTC (rev 1433) +++ shell-tools/trunk/src/bash-commons/common.bash 2009-05-25 18:32:50 UTC (rev 1434) @@ -106,7 +106,9 @@ cpbkup() { eval "$get_all_opts" for file in "$@" ; do - cp $opts "$file" "$file.backup" + dst="$( echo "$file" | sed 's/\/\+$//' ).backup" + echo cp $opts "$file" "$dst" + cp $opts "$file" "$dst" done } @@ -467,14 +469,35 @@ done } -symlink-tree() { +# Reproduce a dir tree (just the dirs). +cp-tree-skel() { local src="$1" dst="$2" find "$src" -type d -printf '%P\0' | xargs -0 -I_ mkdir -p "$dst/_" +} + +# op-tree <src> <dst> <op> [<op args...>] +# Performs operation on each file in the tree. +op-tree-files() { + local src="$1" dst="$2" find "$src" -not -type d -printf '%P\0' | - xargs -0 -I_ ln -s "$( realpath "$src" )/_" "$dst/_" + xargs -0 -I_ "$@" "$( realpath "$src" )/_" "$dst/_" } +# Make a deep copy of a directory. +cp-tree() { + local src="$1" dst="$2" + cp-tree-skel "$src" "$dst" + op-tree-files "$src" "$dst" cp +} + +# Make a deep symlink copy of a directory. +symlink-tree() { + local src="$1" dst="$2" + cp-tree-skel "$src" "$dst" + op-tree-files "$src" "$dst" ln -s +} + rm-empty-dirs() { find "${1:-.}" -type d -empty -print0 | xargs -0r rmdir -p } @@ -526,6 +549,10 @@ sed -i 's/Standards-Version: .*/Standards-Version: 3.8.0/' debian/control } +printable-slides() { + pdfnup --paper letterpaper --nup 2x3 --frame true --scale .9 "$@" +} + flac2mp3() { for i in "$@" do flac -cd "$i" | lame - "${i%flac}mp3" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 18:31:58
|
Revision: 1433 http://assorted.svn.sourceforge.net/assorted/?rev=1433&view=rev Author: yangzhang Date: 2009-05-25 18:31:33 +0000 (Mon, 25 May 2009) Log Message: ----------- also added evan's backtracing method ('lite') Modified Paths: -------------- sandbox/trunk/src/nix/btmalloc/run.bash Added Paths: ----------- sandbox/trunk/src/nix/btmalloc/btlite.c sandbox/trunk/src/nix/btmalloc/btmalloclite.c sandbox/trunk/src/nix/btmalloc/symbolize.py Added: sandbox/trunk/src/nix/btmalloc/btlite.c =================================================================== --- sandbox/trunk/src/nix/btmalloc/btlite.c (rev 0) +++ sandbox/trunk/src/nix/btmalloc/btlite.c 2009-05-25 18:31:33 UTC (rev 1433) @@ -0,0 +1,52 @@ +/* +Preload library to print a stack trace when crashing. + +Evan Jones <ev...@mi...> +March, 2008. + +Based on a version written by Mark Hahn, SHARCnet, 2007. + +Obtained from the beowulf mailing list: +http://article.gmane.org/gmane.comp.clustering.beowulf.general/18463 + +Compile: +gcc -fPIC backtrace.c -shared -o backtrace.so + +Use: +LD_PRELOAD=./backtrace.so ./tester + +Then use addr2line to translate addresses into file/line numbers. + +TODO: +Use some DWARF library to translate addresses into file and line numbers. +Mark Hahn's code linked above uses libbfd. +*/ + +#include <execinfo.h> +#include <signal.h> +#include <unistd.h> + +#define MAX_FRAMES (20) + +static void handler(int sig) { + static const char MESSAGE[] = "\n\nSTACK TRACE:\n"; + write(0, MESSAGE, sizeof(MESSAGE)); + + void* array[MAX_FRAMES]; + size_t size = backtrace(array, sizeof(array)/sizeof(*array)); + backtrace_symbols_fd(array, size, 0); + + // Kill ourselves to propagate the error + raise(sig); +} + +static void __attribute__((constructor)) init() { + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = SA_RESETHAND; + + sigaction(SIGABRT, &sa, 0); + sigaction(SIGFPE, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGSEGV, &sa, 0); +} Copied: sandbox/trunk/src/nix/btmalloc/btmalloclite.c (from rev 1063, sandbox/trunk/src/nix/btmalloc/btmalloc.c) =================================================================== --- sandbox/trunk/src/nix/btmalloc/btmalloclite.c (rev 0) +++ sandbox/trunk/src/nix/btmalloc/btmalloclite.c 2009-05-25 18:31:33 UTC (rev 1433) @@ -0,0 +1,29 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <dlfcn.h> +#include <execinfo.h> +#include <pthread.h> + +#define MAX_FRAMES 20 + +void * +malloc(size_t sz) +{ + // Find and cache the next malloc (in our example it should be the "real" + // malloc). + static void * (*func)(); + if (!func) + func = (void *(*)()) dlsym(RTLD_NEXT, "malloc"); + + void *p = func(sz); + + if (!p) { + printf("Th%lu malloc(%zu) failed!\n", pthread_self(), sz); + + void* array[MAX_FRAMES]; + size_t size = backtrace(array, sizeof(array)/sizeof(*array)); + backtrace_symbols_fd(array, size, 1); + } + + return p; +} Modified: sandbox/trunk/src/nix/btmalloc/run.bash =================================================================== --- sandbox/trunk/src/nix/btmalloc/run.bash 2009-05-25 18:26:32 UTC (rev 1432) +++ sandbox/trunk/src/nix/btmalloc/run.bash 2009-05-25 18:31:33 UTC (rev 1433) @@ -1,3 +1,9 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset + g++ -Wall -g3 -o test test.cc -gcc -Wall -lbfd -ldl -fPIC -shared -o btmalloc.so btmalloc.c #backtrace.c -LD_PRELOAD=./btmalloc.so ./test +gcc -Wall -lbfd -ldl -fPIC -shared -o btmalloc.so btmalloc.c +gcc -Wall -ldl -lpthread -fPIC -shared -o btmalloclite.so btmalloclite.c +LD_PRELOAD=./btmalloc.so ./test || true +LD_PRELOAD=./btmalloclite.so ./test || true Added: sandbox/trunk/src/nix/btmalloc/symbolize.py =================================================================== --- sandbox/trunk/src/nix/btmalloc/symbolize.py (rev 0) +++ sandbox/trunk/src/nix/btmalloc/symbolize.py 2009-05-25 18:31:33 UTC (rev 1433) @@ -0,0 +1,44 @@ +#!/usr/bin/python +# +# Resolves glibc's backtrace output into file and line numbers using addr2line. +# +# Evan Jones <ev...@mi...> +# March, 2008 + +import os +import re +import sys + +ADDR2LINE = "addr2line" +EXTRACT_ADDR = re.compile(r'\[(0x[0-9a-f]+)\]$') + +binary = sys.argv[1] + +addrs = [] +functions = [] +filelines = [] + +# Extract addresses +for line in sys.stdin: + matchobj = EXTRACT_ADDR.search(line) + if matchobj: + addrs.append(matchobj.group(1)) + +# Feed into addr2line +command = ['addr2line', '--demangle', '--functions', '-e', binary] +command.extend(addrs) + +child_in, child_out = os.popen2(command) +child_in.close() +for line in child_out: + line = line.strip() + if len(functions) == len(filelines): + functions.append(line) + else: + filelines.append(line) +code = child_out.close() +assert code is None + +for fileline in filelines: + if fileline.startswith("??"): continue + print fileline This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 18:26:46
|
Revision: 1432 http://assorted.svn.sourceforge.net/assorted/?rev=1432&view=rev Author: yangzhang Date: 2009-05-25 18:26:32 +0000 (Mon, 25 May 2009) Log Message: ----------- added some more puzzles Added Paths: ----------- problems/facebook/untried/Easy Puzzle Mountain.mht problems/facebook/velociraptor/ problems/facebook/velociraptor/analysis problems/facebook/velociraptor/analyze.hs problems/facebook/velociraptor/matrix Added: problems/facebook/untried/Easy Puzzle Mountain.mht =================================================================== --- problems/facebook/untried/Easy Puzzle Mountain.mht (rev 0) +++ problems/facebook/untried/Easy Puzzle Mountain.mht 2009-05-25 18:26:32 UTC (rev 1432) @@ -0,0 +1,3002 @@ +Content-Type: multipart/related; start=<op.mhtml.1176054483768.a9e9963250371833@127.0.1.1>; boundary=----------baYQE7JahMjuMBxFf0oq6T +Content-Location: http://mit.facebook.com/jobs_puzzles/?puzzle_id=6 +Subject: =?utf-8?Q?Facebook=20|=20Programming=20Puzzles?= +MIME-Version: 1.0 + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=default.htm +Content-Type: text/html; name=default.htm +Content-Id: <op.mhtml.1176054483768.a9e9963250371833@127.0.1.1> +Content-Location: http://mit.facebook.com/jobs_puzzles/?puzzle_id=6 +Content-Transfer-Encoding: Quoted-Printable + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"en" lang=3D"en"= + id=3D"facebook"> +<head> +<title>Facebook | Programming Puzzles</title> +<meta http-equiv=3D"Content-type" content=3D"text/html; charset=3Dutf-8"= + /> +<link rel=3D"search" type=3D"application/opensearchdescription+xml" href= +=3D"http://static.ak.facebook.com/opensearch_desc.xml?6:27839" title=3D"= +Facebook" /> +<link rel=3D"stylesheet" href=3D"http://static.ak.facebook.com/css/base.= +css?6:33957" type=3D"text/css" /> +<link rel=3D"stylesheet" href=3D"http://static.ak.facebook.com/css/faceb= +ook.css?6:35343" type=3D"text/css" /> +<link rel=3D"stylesheet" href=3D"http://static.ak.facebook.com/css/faceb= +ookpro.css?6:37391" type=3D"text/css" /> +<link rel=3D"stylesheet" href=3D"http://static.ak.facebook.com/css/nonpr= +oduct.css?6:26792" type=3D"text/css" /> +<link rel=3D"stylesheet" href=3D"http://static.ak.facebook.com/css/jobs_= +engineering.css?6:35282" type=3D"text/css" /> +<!--[if lte IE 6]><style type=3D"text/css" media=3D"screen">/* <![CDATA[= + */ @import url(http://static.ak.facebook.com/css/ie6.css?6:37522); /* ]= +]> */</style><![endif]--> +<!--[if gte IE 7]><style type=3D"text/css" media=3D"screen">/* <![CDATA[= + */ @import url(http://static.ak.facebook.com/css/ie7.css?6:37522); /* ]= +]> */</style><![endif]--> +<script type=3D"text/javascript" src=3D"http://static.ak.facebook.com/js= +/base.js?6:35674"></script> +<script type=3D"text/javascript" src=3D"http://static.ak.facebook.com/js= +/ajax.js?6:36568"></script> +<link rel=3D"shortcut icon" href=3D"http://static.ak.facebook.com/favico= +n.ico" /> + +</head> +<body class=3D"jobs"> +<div id=3D"book"> +<div id=3D"pageheader"> +<h1 id=3D"homelink"><a href=3D"http://mit.facebook.com">Facebook</a></h1= +> +<ul id=3D"gnav"><li><a href=3D"http://mit.facebook.com/home.php?">home</= +a></li> +<li><a href=3D"http://mit.facebook.com/s.php">search</a></li> +<li><a href=3D"http://mit.facebook.com/b.php">browse</a></li> +<li><a href=3D"http://mit.facebook.com/invite.php">invite</a></li> +<li><a href=3D"http://mit.facebook.com/help.php">help</a></li> +<li><a href=3D"http://mit.facebook.com/logout.php?h=3D40f0b1e5d52042079c= +569f5fe20884aa">logout</a></li> +</ul> +</div> +<div id=3D"sidebar"><div id=3D"qsearch"><form method=3D"get" action=3D"h= +ttp://mit.facebook.com/s.php" name=3D"qsearch"><input type=3D"search" cl= +ass=3D"inputtext inputsearch" placeholder=3D"Search" autosave=3D"com.fac= +ebook.qsearch" id=3D"q" name=3D"q" value=3D"" results=3D"10" /><script t= +ype=3D"text/javascript">placeholderSetup('q');</script></form></div><ol = +id=3D"nav"> +<li id=3D"myprofile"><a href=3D"http://mit.facebook.com/profile.php?id=3D= +708869" class=3D"hasedit">My Profile</a><a href=3D"http://mit.facebook.c= +om/editprofile.php" class=3D"edit">edit</a></li> +<li id=3D"myfriends"><a href=3D"http://mit.facebook.com/friends.php?r">M= +y Friends</a></li> +<li ><a href=3D"http://mit.facebook.com/photos.php?id=3D708869">My Photo= +s</a></li> +<li><a href=3D"http://mit.facebook.com/shared.php">My Shares</a></li> +<li><a href=3D"http://mit.facebook.com/notes.php">My Notes</a></li> +<li><a href=3D"http://mit.facebook.com/groups.php">My Groups</a></li> +<li><a href=3D"http://mit.facebook.com/events.php">My Events</a></li> +<li><a href=3D"http://mit.facebook.com/mailbox.php">My Messages</a></li>= + +<li><a href=3D"http://mit.facebook.com/mobile.php">My Mobile</a></li> +<li><a href=3D"http://mit.facebook.com/account.php">My Account</a></li> +<li><a href=3D"http://mit.facebook.com/privacy.php">My Privacy</a></li> +</ol> +<div id=3D"ssponsor" class=3D"sponsors"></div></div> +<div id=3D"pagebody" class=3D"pagebody jobs"><div id=3D"header"> + <h1>Programming Puzzles</h1> +</div> +<div id=3D"content"> +<div class=3D"bar clearfix tab_bar"><div id=3D"tabs"><div id=3D"jobs_tab= +" class=3D"inactivetab"><a href=3D"../jobs.php">Jobs</a></div> +<div id=3D"engineering_tab" class=3D"inactivetab"><a href=3D"../jobs_eng= +ineering.php">Engineering</a></div> +<div id=3D"puzzle_tab" class=3D"activetab"><a href=3D"../jobs_puzzles/">= +Puzzles</a></div> +<div id=3D"quotes_tab" class=3D"inactivetab"><a href=3D"../jobs_quotes.p= +hp">Perspectives</a></div> +<div id=3D"apply_tab" class=3D"inactivetab"><a href=3D"http://tbe.taleo.= +net/NA3/ats/careers/searchResults.jsp?org=3DFACEBOOK&cws=3D1">Apply</a><= +/div> +</div></div><div class=3D"column text_column"><div class=3D"wrapper"> + <br/> +<h3>Easy Puzzle Mountain</h3> + +<br/> + +<h4>Part 1:</h4> + +How many bytes long is the sequence for the code point whose UTF-8 = + +representation begins with 0xE3? + +<br/><br/><br/> + +<h4>Part 2:</h4> + +<div class=3D"puzcode"> +<pre> + 0xA9 0xE3 0xB4 0xB1 0x54 0x98 0xB4 0x77 + 0x88 0x01 0xB2 0x8E 0x5D 0xAA 0xBB 0x66 + 0x9A 0xC4 0xB2 0x3F 0x8C 0xA3 0xDF 0xA0 + 0x90 0x4A 0x83 0x90 0x00 0xA2 0xA7 0x94 + 0x83 0x5C 0x5B 0x86 0x91 0xBF 0xAA 0x60 + 0xA1 0x47 0x89 0xB2 0xC4 0x89 0x50 0x99 +</pre> +</div> + +<br/><br/> + +Decode the puzzle and send the answer to Part 1, plus any code you = + +might have written to decode Part 2 (and a resume) to: + +<br/><br/> + +<b>{ Answer to Part 2 } @ facebook.com</b> + +<br/><br/> + +Please put <b>[utf8]</b> in the subject line. = + + + +<br/><br/> + +[ <a href=3D"index.php">Back to the list of puzzles</a> ] + +<br/><br/> + + +</div> +</div><div id=3D"spotlights" class=3D"column pics_column"><img id=3D"t35= +00002" style=3D"width:50px" src=3D"http://profile.ak.facebook.com/profil= +e/1035/91/t3500002_13343.jpg" /><img id=3D"t204686" style=3D"width:50px"= + src=3D"http://profile.ak.facebook.com/v52/1013/28/t204686_6698.jpg" /><= +img id=3D"t500018751" style=3D"width:50px" src=3D"http://profile.ak.face= +book.com/profile2/1104/44/t500018751_27944.jpg" /><img id=3D"t210081" st= +yle=3D"width:50px" src=3D"http://profile.ak.facebook.com/profile2/547/27= +/t210081_24677.jpg" /><img id=3D"t1208381" style=3D"width:50px" src=3D"h= +ttp://profile.ak.facebook.com/profile2/1918/60/t1208381_23997.jpg" /><im= +g id=3D"t10030226" style=3D"width:50px" src=3D"http://profile.ak.faceboo= +k.com/v52/1748/88/t10030226_8783.jpg" /><img id=3D"t1160" style=3D"width= +:50px" src=3D"http://profile.ak.facebook.com/v52/550/32/t1160_1561.jpg" = +/><img id=3D"t708561" style=3D"width:50px" src=3D"http://profile.ak.face= +book.com/profile2/1482/72/t708561_21203.jpg" /><img id=3D"t217594" style= +=3D"width:50px" src=3D"http://profile.ak.facebook.com/v52/863/24/t217594= +_5746.jpg" /><img id=3D"t4801917" style=3D"width:50px" src=3D"http://pro= +file.ak.facebook.com/profile2/1119/72/t4801917_29701.jpg" /><img id=3D"t= +211805" style=3D"width:50px" src=3D"http://profile.ak.facebook.com/profi= +le2/847/2/t211805_26558.jpg" /><img id=3D"t4809639" style=3D"width:50px"= + src=3D"http://profile.ak.facebook.com/profile2/328/66/t4809639_22173.jp= +g" /><img id=3D"t703" style=3D"width:50px" src=3D"http://profile.ak.face= +book.com/profile2/898/115/t703_23152.jpg" /><img id=3D"t10" style=3D"wid= +th:50px" src=3D"http://profile.ak.facebook.com/v52/321/93/t10_5214.jpg" = +/></div><script type=3D"text/javascript"> +function set_opacity(obj, o) { + try { + obj.style.opacity=3Do; + obj.style.filter=3D'alpha(opacity=3D'+o*100+')'; + } catch (e) {} +} + +function get_opacity(obj) { + if (obj.style.opacity!=3Dnull) + return parseFloat(obj.style.opacity); + else { + var r=3D/alpha\(opacity=3D([^)]+)\)/; + return parseFloat(r.exec(obj.style.filter)[1])/100; + } +} + +function fade_picture(obj, targ, key, tim) { + var oo; + if (key!=3D0 && obj.getAttribute('fk')!=3Dkey) // another fade call ha= +s been made, overriding this one + return; + else if (key=3D=3D0) { // this is the first time calling the function + obj.setAttribute('fk', key=3DMath.ceil(Math.random()*32768)); + obj.setAttribute('oo', oo=3Dget_opacity(obj)); + tim=3D(new Date).getTime(); + } + else // called by setTimeout + oo=3DparseFloat(obj.getAttribute('oo')); + var no=3Doo+(((new Date).getTime()-tim)/500)*(targ>oo?1:-1); + no=3D(oo<targ)?Math.min(no, targ):Math.max(no, targ); + try { // inline copy of set_opacity for presumably faster changing + obj.style.opacity=3Dno; + obj.style.filter=3D'alpha(opacity=3D'+no*100+')'; + } catch (e) {} + if ((oo<targ&&no<targ) || (oo>targ&&no>targ)) + setTimeout(function(){fade_picture(obj, targ, key, tim)}, 10); +} + +function spotlight_picture(obj) { + var parent=3Dnull; + if (obj.tagName.toString().toLowerCase()=3D=3D'img') { + parent=3Dobj.parentNode.parentNode; + } + else { + parent=3Dobj; + obj=3Dnull; + } + img=3Dparent.getElementsByTagName('img'); + for (var i=3D0; i<img.length; i++) { + if (img[i]=3D=3Dobj || obj=3D=3Dnull) + fade_picture(img[i], 1, 0); + else + fade_picture(img[i], 0.25, 0); + } +} + +var p=3D/t([0-9]+)/; +var img=3Ddocument.getElementsByTagName('img'); +for (var i=3D0; i<img.length; i++) { + if (p.test(img[i].id)) { + set_opacity(img[i], 1); + img[i].onmouseover=3Dfunction(){spotlight_picture(this)}; + img[i].onmouseout=3Dfunction(){spotlight_picture(this.parentNode)}; + } +} +</script> </div> +<!-- content --> +<div id=3D"pagefooter"> +<ul id=3D"fnav"> +<li><a href=3D"http://mit.facebook.com/about.php">about</a></li> +<li><a href=3D"http://blog.facebook.com">blog</a></li> +<li><a href=3D"http://developers.facebook.com">developers</a></li> +<li><a href=3D"http://mit.facebook.com/jobs.php">jobs</a></li> +<li><a href=3D"http://mit.facebook.com/terms.php">terms</a></li> +<li><a href=3D"http://mit.facebook.com/policy.php">privacy</a></li> +<li><a href=3D"http://mit.facebook.com/advertise.php">advertise</a></li>= + + +</ul> + +<p>a Mark Zuckerberg production</p> +<p>Facebook <span title=3D"42">©</span> <span title=3D"10.1.2.177">= +20</span><span title=3D"6757048">07</span></p> +</div> +</div> +<!-- book --> +<!-- ads --> +<div class=3D"sponsors" style=3D"width: 760px; text-align: center; clear= +: both; margin: 10px auto 15px auto;"></div> +<!-- ads --> + +<!-- Start Quantcast tag --> +<script type=3D"text/javascript" src=3D"http://edge.quantserve.com/quant= +.js"></script> +<script type=3D"text/javascript">_qacct=3D"p-cfa3mzpjPgEN6";_qmeta=3D"qc= +:id=3D6fa2fd967c60affc7f9a6d6ddb7a54a8";quantserve();</script> +<!-- End Quantcast tag --> + +</body> +</html> + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=magglass.png +Content-Type: image/png; name=magglass.png +Content-Location: http://static.ak.facebook.com/images/magglass.png +Content-Transfer-Encoding: Base64 + +iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAIAAAAmzuBxAAAABGdBTUEAALGPC/xh +BQAAAH1JREFUKFN9UDEOgCAMxBhd3Ez8/7fcXByM6aBj1YAHJRUheukA1+txpXLO +MTNtbBIMfdc2dST4uOZlH6c1LTDgMQwYbZ8BaIgUfFTIHT25AzgL+alQm5dCX7XW +5h6aAyIpCfHkKHeRGV3H+P8IC2elIq8oocZEZBDtRwTjG3NoQFU9t7qUAAAAAElF +TkSuQmCC +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=base.css +Content-Type: text/css; name=base.css +Content-Location: http://static.ak.facebook.com/css/base.css?6:33957 +Content-Transfer-Encoding: 8bit + + +/* ------------------------------------------------------------------------ + Facebook + ------------------------------------------------------------------------ */ + +body { + background: #fff; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; + font-size: 11px; + margin: 0px; + padding: 0px; + text-align: left; } + +h1, h2, h3 { + margin: 0px; + padding: 0px; } + +h2 { + color: #3b5998 } + +p { + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; + font-size: 11px; + text-align: left; } + +a { + color: #3b5998; + text-decoration: none; } + +img { + border: 0px; } + +td, +td.label { + text-align: left; } + + +/* --------------------------| GLOBAL CLASSES |-------------------------- */ + + +#error { + margin: 0px 10px 10px; + padding: 10px; + border: solid 1px #dd3c10; + background: #ffebe8; } + +#error h1 { + font-size: ; +} + +#error p { + margin: 4px 0px 0px; } + +#error a { + text-decoration: none; + color: #dd3c10; } + + + +.status { + margin: 0px 10px 10px; + padding: 10px; + border: solid 1px #ffe222; + background: #fffbe2; } + +.status h2 { + color: black; + font-size: 11px; + margin: 0px; } + +.status p { + margin: 4px 0px 0px; } + +.status a { + text-decoration: none; } + + + +.pipe { + color: gray; + padding: 0px 3px; } + +.column { + float: left; } + + + +/* ----------------------| SWEET BLESSED CLEARFIX |---------------------- */ + +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden;} + +/* Hides from IE-mac \*/ +* html .clearfix { height: 1%; } +.clearfix { display: block; } +/* End hide from IE-mac */ + + + +/* ------------------------------| FORMS |------------------------------- */ + +form { + margin: 0px; + padding: 0px; } + +label { + color: gray; + font-weight: bold; } + + +.formtable { + margin: 0px auto; } + +.formtable { + margin: 0px; } + +.formtable td { + border: none; + margin: 0px; + padding: 3px 1px; } + +.formtable td.label { + color: gray; + font-weight: bold; + padding-right: 10px; } + +.formtable tr.tallrow { + vertical-align: top; } + +.formbuttons { + text-align: center; + margin: 10px 10px; } + +.formbuttons .inputsubmit, .formbuttons .inputbutton { + margin: 2px 4px; } + +.formbuttons .securetoggle { + padding: 9px 0px 0px 0px; } + + +/* FORM INPUTS */ + +.inputtext, +.inputpassword { + border: 1px solid #bdc7d8; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; + font-size: 11px; + padding: 3px; } + +textarea { + border: 1px solid #bdc7d8; + padding: 3px; + font-size: 11px; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; } + +.inputbutton, +.inputsubmit { + border-style: solid; + border-top-width: 1px; + border-left-width: 1px; + border-bottom-width: 1px; + border-right-width: 1px; + border-top-color: #D9DFEA; + border-left-color: #D9DFEA; + border-bottom-color: #0e1f5b; + border-right-color: #0e1f5b; + background-color: #3b5998; + color: #FFFFFF; + font-size: 11px; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; } + +.inputcheckbox { + border: 0px; } + +.inputsearch { + background: white url(/images/magglass.png) no-repeat 3px 4px; + padding-left: 17px; } + +.transparent_png_ie6 { + display: none; +} + +#inline_flyer { + background-color: #efeded; + color: #909090; + border-bottom: 1px solid #d8dfea; + padding: 4px 10px 2px 10px; +} + +#inline_flyer .external_link a { + text-decoration: none; + border-bottom: 1px dotted #3b5998; +} + +#inline_flyer .external_link a:hover { + text-decoration: none; + border-bottom: 1px dotted #efeded; +} + +#inline_flyer #abbreviated_body { + float: left; + width: 430px; +} + +#inline_flyer #expander { + float: right; +} + +#inline_flyer_content { + background-color: #efeded; + border-bottom: 1px solid #d8dfea; + padding: 4px 10px; +} + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=pageheaderbg.gif +Content-Type: image/gif; name=pageheaderbg.gif +Content-Location: http://static.ak.facebook.com/images/pageheaderbg.gif +Content-Transfer-Encoding: Base64 + +R0lGODlh+AIhAPcAAK2802uCscvU49zi7cXO4bXC17zI29/k7uns89fe6ebq8k1o +odPa6Nfe6tTb6HSKttvg7NHZ57/K3aKwzsjQ4vn6/HmOuc3W5Ozv9evu9EpmoLjF +2cTP37rE29Lb532Ru153q+Hm78PO30Bem8PM36++1P3+/r7I3fDy956tzPj5++3w +9a671bzG3HKIte/y9rjC2czW5OLm8ODl7kdjnszU5G6Fs9bc6lRupYmbwc/Y5e7x +9pamyGF6rMjS4tje6pioyc/W5rjG2URhncrT4j5cmvT2+ZuqylFspLTA2HCGtOXq +8aq60qq309bd6YOWvoGUvVZwp9Ha5+fs8ujr8khkn5Chxay70qe00aWz0MHK3oia +wLC81W2DslpzqIyew1Bro8jQ4WV8rrG/1dng66+91LTB1rC+1LC+1dng6v7+/zxa +mPr7/bfE2P39/qSyz2d+rz1amdrg69Xc6bO/13eMuOrt9Pz8/dvh67PB1sfP4lt0 +qbPA1j1bmbK/1dzh7PHz+LrH2szT5Ku40+To8fv8/WZ9r/7+/q691Pf4+7G91kNg +nOnt9Ki10brG2rvH2tXc6LLA1uXp8cLL3+3w9sXP4PH0+LLA1UJfnGh/sMjR4tTc +6PL0+M/X5v79/vr6/P39/fz9/pyry8HM3n+SvLC/1Y6fxPX3+sfS4fb3+o+gxPr7 +/OPn8K251PP1+ZKjxs7V5drh68fQ4PP2+YeZwF94q8vT5Iqcwr3J24SXvrHA1ff5 ++9vi7Gh/r7bB2bvH2/v7/bvF28jS4ePo8MbQ4MbR4LbD2MDL3fL1+N7j7pGixeTp +8Fx1qaGwzvb4+rTB15+uzcfR4LG+1dPb6O7w9ZSlx9HY5dPc6MTN4Njg62B4q93j +7bXB1r/M3bnG2b3K3Jqpytvi6+ru87zH2pOkxrXD2Km20vT1+Vhyp/v7/Nrh6p2s +y4KVvcvV47nF2mR8rdHZ5+nu88bQ4cbR4YaYv8fQ4au60v7///L1+fP0+LPB17S/ +1/b4+9jf6v///ztZmCH5BAAAAAAALAAAAAD4AiEAAAj/AP0BIzSgn8GDCBP2K8bH +jJk23KKtYOiwosM2xwQ0UOGv4w5UBSyKHGmGzzxeZFKqXElGocuXMGPKRKhJyYJ/ +OHPq3Mmzp8+fQIMKHUq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWJ8i+WDHXwU8MxOm +qXRmTBkDF+zsKFB2jFu3fAZw7EiXTaw2aN7q3fu2lAgHYQMLHuxy0pCsiBMrXsy4 +sePHkCNLnkz5cZUDhAj3S8OhbJlAGEww8lOCj663ZdpYokvXiI4NfMeUaLu3RKAL +9eak0cy7t0IllYMLH068uPHjyJMrt2oBLGHOnr3NMiHMDCsMIsq4RSTgDmt//GJU +/xL2qExe2WgutPOzF00ZH3KcNPBN3/fh5fjz69/Pv7///5UNwRsZArhVxgaWVAAP +Ah31o10JeTD43SpGGFHJJW0UUEoJBQjgySxtlPBWXhz001J9KGoG4IostujiizDG +SBlvaSTwi3ZnhPCdJcaUUMYxhXxHlyfXcKCACFc8Es8q/jjziIhjoFFANGmcmOKV +gcmo5ZZcdunll//1JocOBbgXDSjfbeMjA0KytsMmsphhjwB07YKLiFJ2IgeWfGYJ +5p+ABirooIQiReMmUsgyhh9mZPBdBbhcoUCbrKkwij2OMEJXBceIWEY3VvYp6ktD +1ZICDB0EYwFWfWhgCAhXjf8ARhdgFGrrrbjmCuChuLThVglSCMmKCPhQStcMBfjw +QqV3jnEJEXuOKq1CQllgBGvQXNWDAxiowYJVtPzhij+r6mruueim+1hvaVzgTh5m +tbHsd4WYYGxHKGCAJmvOBCLiJQKEOu20QQ0xw3fZWvUAXYNY1Qhddagr8cQUV5yU +b2Q0gIqBuGh678eVfiOiH0QIPPCoQYHARkeADPKGDVe5QFcTVr0BscU456wzxfTJ +0ZlbTAQL8tB3EKMdySaf3GdQcNAFA2Iyd0RzVTZ3FPHOWGetdaD0QSdbORgMLbY1 +ZZTChw5JK41lynS1ktQaRkXtTxY4wS1V1f5cvfXefPf/vSJ9ZHQSyRgACOCG2EM7 +UcYZo6h98k9gNEHCsSz4YkMUdCiieSNWvLNTD9AQ0AksLYhSC0405NACLEFIYMVN +/8ityRuadELBBF7olEkWenSiySAu7BQFEJMEIYgvT2CCE95XB5CEIr68Yrff1Fdv +vWT1NWAAAAV4jPjHMyDiCCRpO57iTyBQSk8dQrKRRRw4ATEXa2/8s8cfQiqQSezG +7tDDP3F4g3e+A4MR4AQKgBASA3DwD+b9gwYyoEu5rkfBClqwKhiLBR6mYYxofK9N +hTjAARKhBkuMogDwKJ/5UIQ+SnVBFZR6wD8+QKkJrAEWdLnDyjoSghHY4F5Pe4Kx +/47wDxAkglIE+Eczboa3b13wiVCM4lHYtYkLEKETx5jCB4VUgSVsMAGOOAMR1LFC +gvlkAY3QAl2SMQgWgOEBdGBBKxQxDLo04h81oEsLTPGFI5yAHXuwlz/m0ANmUIAu +XcgEXTBgDlNMgi4/KIIg6KIFVSRBkMMowgTocgNlNONa/rgDDkRBFxswYy5UgJ0U +V8nKVg4IHhuIhB/EqIYttukcEmhDahJQRjO2sCNO5IkhDucPGAyhK/74A09IQRce +HJAut+jFzHBSBUp05A9IoEJHZmDAf3SiI4nAgRq9AqsG0uUBQOiIGh5wyI5AoZXw +jOcTe/MN85QhEt6zJV0O4f8BRIzhDCLopS990rSO0EEnC+iBIXrwgU90pAMLSKA/ +asCTXNCFCvBgACvoYoWC+mNqQ5BERyAQBWv6wwHw+0cLOqICELQTEEjAiSno8oF0 ++oMN7fRHC+TJ055SjzczMEBeAHABT9gSFIAIBV1WYAztSCNgAkUZUDx60H9gohEZ +cIMatkoXiEoUFjwRorGqYYhpPnBS/iBp2AZZBJxIgKUg0ENHOMHAf1iBpjatpTph +5tO++lVnmknAC3RQhjIYY14fdEUYylGJKewiFEswQwmkJIXdRHVpU6VLVXlgLK92 +hKI7sWhHkkECPZhWD5p4QADMGtKRlrQjDugDTk4A15f/1hWGHalpR9hAAr1iY3p/ +Da5wzUWYBBwgFBnIAyKEtkUHREIC4xACLiQQiNOcIRBOsOxl15ZZg+Lkm/74xDpI +QY4ddqAKa3UAT2jYEXD0RG53fOAOOiIHMCATAjmRqz8SgY7J+eMUdeWs1fL6AP36 +453DTbCCCaUZavjDDQJ4xin0CYgVrEIFL1gGEd5SAmKocLu8YZpmcTIHlt0kE0HS +aRxKHN4jBCATdeCBDdAxQEmQwhCZcMETjrCAH3YkGHswBAvoYosisJgNKeiFMlLR +ETuMYBB0CUYAPoBWf+zhCKXURooJUYUFe/nLXRpMApKRjo68wBFSUKqxVICCoZ2i +/w1nOAMKPwxiwojYuyqlywAEMa6OnMCulKqfJoy1h9XShZh0ecU/BNwmt3XBWDeI +AzRuxgW61A/MmM40i8QsDtbwAg1LuNcqIKGj76gBBSGYgRwgIQIDiUC7dT4fUBTZ +kaf9IwA7FBIJ/lGEDrSJbl44AKX24OM2EeAwmHikkOABuxS0yQ5i+MfDOrIqMKxV +DXDQtLa3nR/BNAAP83swB6bxsVREYwDfuQMqrgAARJTBUwbIbqy5iz4HOOAGRMTJ +A4LACAUI4hbQgIAcsICTODxBD6zIAAL+QILg/WMBooCHAjDACFbAYx8awEESbDEA +BdgBAQcgwBa6yWta6GEGVP9ghSBecR99t6DjkoDHG+pqihs4YA4BwMkT5uAAJ7wB +uNwOutBnFJYGNKDT35lCAg7xMU44Yul0UQMnluADKJ3BG9Og87wFE5Q19KEPRUhp +TmjQ8hGMoK06WYQGaEDynKyBBhqowiKAPgK4V0F5PlkEDRbxkxEMYQhiB2ARwD69 +wRdhBEAfuuIXr5iwJGAbO2D6d5bhhKGxAhE6yHVH3OCBf+ahE87ZuqwZT/rSw1Mm +DcgGAirQJjeMgtwgM4Em7CECky4yD2X4RgO0LvqwmP73wJ/nSxqQgBlwwlghAAA8 +xEaFPFxhA9tIhAlMsAMRlOAS7Qh97+sT/O5732/aP0iMAsgwBWAYCxmPuMLyjeWG +I/rjEJUAgHY2UAkRFABPQiBCAqK1fd98//8AqDOZkRAJEALIcC/3AAkAAADtIEht +ogLyQAj+sAxw5hZnUAKTNSJjgBb9wH/9Z2cBGIIiiC5fgRB4IA4DZCypgAuIAAAi +wCSUkg/P8Avh0FSxURv68A0X8IEhNoI++IOEEhAAOw== + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=facebook.css +Content-Type: text/css; name=facebook.css +Content-Location: http://static.ak.facebook.com/css/facebook.css?6:35343 +Content-Transfer-Encoding: 8bit + + +/* ------------------------------------------------------------------------ + Facebook | Standard Page + ------------------------------------------------------------------------ */ + +/* Standard Page Styles */ + +#book { + padding: 8px 0px 0px 0px; + margin: 0px auto; + text-align: left; + width: 760px; } + +#pageheader { + background: #3b5998 url(/images/pageheaderbg.gif) no-repeat top left; + height: 33px; + position: relative; + width: 760px; } + +#homelink { + height: 33px; + left: 132px; + position: absolute; + width: 118px; } + +#gnav { + left: 250px; + line-height: 25px; + list-style: none; + margin: 0px; + padding: 3px 0px; + position: absolute; + text-align: right; + top: 1px; + width: 500px;} + + #gnav li { + display: inline; } + #gnav a { + color: #D8DFEA; + margin: auto 0px; + padding: 2px 4px; } + #gnav a:hover { + background-color: #526DA4; + color: white; } + +#sidebar { + float: left; + padding: 6px 0px 10px 0px; + width: 120px; } + + #sidebar .adtable { /* For Backwards Compat with Ads */ border: solid 1px lightgrey; } + +#snav { + border-bottom: solid 1px white; /* firefox fix */ + margin: 0px 0px 10px 0px; + padding: 0px; } + + #snav a { + border-bottom: solid 1px #D8DFEA; + padding: 2px 3px; + margin: 0px; + width: 114px; + display: block; + float: left; } + #snav a:hover { text-decoration: none; color: white; background: #3B5998; } + #snav a.hasedit { width: 68px; } + #snav a.edit { + width: 40px; + color: gray; + text-align: center; } + #snav a.edit:hover { color: white; } + +#ssystemstatus { + width: 120px; + margin: 0px 0px 10px; + padding: 10px; + border: solid 1px #dd3c10; + background: #ffebe8; } + +#squicklogin { + width: 120px; + margin: 0px 0px 10px; + padding: 0px; } + + #squicklogin label { + display: block; + padding: 0px 0px 2px; + margin: 0px; + color: gray; + font-weight: bold; } + + #squicklogin table { + border-width: 0px; + border-style: none; + border-collapse: collapse; + border-spacing: 0px; + margin: 3px 0px 0px 0px; + } + #squicklogin td { + text-align: center; + border: none; + padding: 0px 0px 3px 0px; + } + #squicklogin .inputtext { width: 115px; } + +#qsearch { + padding: 2px 0px 0px 0px; } + +#qsearch #q { + width: 115px; } + +#qsearch.hourglass #q { + padding-left: 17px; + width: 98px; } + + +#ssponsor { margin: 10px 0px; color: grey; } + + #ssponsor a:hover { text-decoration: underline; } + #ssponsor table.adtable { color: black; } + #ssponsor table.adtable a:hover { text-decoration: underline; } + +#pagebody { + font-size: 11px; + margin-left: 12px; + float: left; + text-align: left; + width: 628px; + } + +/* HACKED because IE SUCKS ASS */ +* html #pagebody { + f\loat: right; + margin: 0px; + c\lear: both; + text-align: left; + o\verflow: hidden; } + + .pagebody a:hover { text-decoration: underline; } + +#content { + padding: 12px 0px; + border-bottom: solid 1px #3B5998; + border-left: solid 1px #D8DFEA; + border-right: solid 1px #D8DFEA; } + + #content:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } + /* #content li a:hover { text-decoration: none; } */ + +/* Hides from IE-Mac \*/ +* html #content { height: 1%; } +/* End hide from IE-Mac */ +.note_dialog { + background: #fff; + padding: 10px; + margin: 0 10px 10px 10px; + border: 1px solid #bdc7d8; + color: #444; } + +#header { + font-weight: bold; + line-height: 23px; + font-size: 14px; + padding: 0px 10px 0px; + margin: 0px; + background: #6d84b4; + color: white; + border-bottom: solid 1px #3B5998; } + + /* #header.withsubheader { border-bottom: none; } */ + #header.withsubtitle { text-align: right; } + #header.withsubtitle h1 { float: left; text-align:left;} + +#subheader { + text-align: left; + color: #3B5998; + font-weight: bold; + line-height: 21px; + font-size: 11px; + margin: 0px; + padding: 10px 10px 0px; + background: white; + border: solid 1px #D8DFEA; + border-top: none; } + + #subheader.withsubtitle, #footer.withsubtitle { text-align: right; } + #subheader.withsubtitle h2, #footer.withsubtitle h2 { float: left; text-align: left;} + #subheader div { font-weight: normal; } + #subheader a { font-weight: normal; } + +#footer { + text-align: center; + color: #3B5998; + font-weight: bold; + line-height: 21px; + font-size: 11px; + margin: 0px; + padding: 0px 10px; + background: #D8DFEA; + border-bottom: solid 1px #3B5998; } + +h1 { font-size: 14px; } + + h1 a { color: white; text-decoration: none; } + h1 a:hover { color: white; text-decoration: underline; } + h1 em { font-style: normal; border-bottom: solid 1px #D8DFEA; } + h1 .subtitle { } /* Reserved */ + +h2 { font-size: 11px; } + + h2 .subtitle { } /* Reserved */ + +h3 { + color: #444; + font-size: 11px; + font-weight: normal; } + +h4 { + color: #3B5998; + font-size: 11px; + margin: 0px 0px 6px 8px; } + + h4 .edit { display: inline; margin-left: 8px; } + h4 .edit a { color: lightgrey; } + h4 .edit a:hover { color: #3B5998; } + +h5 { + color: #3B5998; + font-size: 11px; + margin: 0px 0px 6px 8px; } + + h5 .edit { display: inline; margin-left: 8px; } + h5 .edit a { color: lightgrey; } + h5 .edit a:hover { color: #3B5998; } + + +#tabs { + text-align: center; + padding: 4px 0px; + margin: 10px 20px 10px; + border-bottom: solid 1px #3B5998; } + +#tabs div { + display: inline; + padding: 0px; + margin: 0px; } +* html #tabs div { + margin: 0 3px; } + + +#tabs a { + margin: 0px; + padding: 4px; } + +#tabs .activetab a { + color: white; + background: #3B5998; } + +#tabs .activetab a:hover { + text-decoration: none; } + +#tabs .inactivetab a:hover { + background: #D8DFEA; + text-decoration: none; } + +#tabs .disabled { + color: #c0c0c0; + margin: 0px; + padding: 4px; + text-decoration: none; } + +#pagefooter { + clear: both; + font-size: 10px; + line-height: 15px; + padding: 10px 0px; + border-top: solid 1px #D8DFEA; } + + #pagefooter a { padding: 3px 5px; } + #pagefooter a:hover { color: white; background: #3B5998; text-decoration: none; } + #pagefooter p { text-align: center; margin: 0; padding: 0; } + + +.infotable { + margin: 0px; } + +.infotable td { + vertical-align: top; + font-size: 11px; + margin: 0px; + padding: 0px; + padding-bottom: 2px; } + +.infotable td.label { + padding-right: 10px; + color: gray; } + +.pager { + padding-left: 4px; + text-align: right; } + + .pager b { + padding: 2px; + font-style: normal; + font-weight: bold; + color: #3B5998; + border-bottom: solid 2px } + .pager a { + font-weight: normal; + margin: 0px; + padding: 3px 3px; } + .pager a:hover { + color: white; + margin: 0px; + padding: 3px 3px; + background: #3B5998; } + + #toppager a:hover, #bottompager a:hover { + text-decoration: none; } + + #toppager b { + border-bottom: solid 2px #3B5998; } + + #bottompager b { + border-bottom: none; + border-top: solid 2px #3B5998; } + #bottompager.flip b { + border-top: none; + border-bottom: solid 2px #3B5998; } + +#suggest { + position: absolute; + background: #fff; + width: 150px; } + + #suggest div { + background: #fff; + color: #000; + padding-left: 4px; + text-align: left; } + + #suggest div.over { + color: #fff; + background: #000; } + +/* Miscellaneous */ + +.center { + margin-left: auto; + margin-right: auto; +} + +div.clear { + clear: both; } + +.bluebox { + margin-left: auto; margin-right: auto; width: 532px; padding: 5px 0; } + +.allfrom { border: 0; } +#chk { border: 0; } + +select { + border: 1px solid #bdc7d8; + padding: 2px; + font-size: 11px; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif } + +/* Eww.. blue boxes. */ + +.blueheader h2 { + color: #3B5998; + font-size: 11px; } + +.blueheader { + margin: 0px; + padding: 2px 8px; + font-size: 11px; + font-weight: bold; + color: #3B5998; + background: #D8DFEA; + border-top: solid 1px #3B5998; } /* #8a9cc1; } */ + + .witheditlink { text-align: right; } + .witheditlink h2 { float: left; } + +.bluesubheader { + color: #3B5998; + font-weight: bold; + font-size: 12px; + margin: 0px; + padding: 2px 8px; + background: #eee; + border-top: solid 1px #ccc; } + +.bluecontainer { + padding: 10px 8px; } + + +/* Ads */ +#announce2 { + width: 120px; + font-size: 11px; } + + #announce2 div.advert { + margin: 0px auto; + height: 120px; + display: block; + line-height: 14px; + background: #f9f9f9; + border: solid 1px #D8DFEA; + border-bottom: solid 1px #3B5998; + margin: 0px 0px 7px; + padding: 1px 0px 2px; } + #announce2 div.clickable { + cursor: pointer; } + #announce2 p { + margin: 0px 0px 3px 5px; + overflow: hidden; + width: 110px; + color: #222222; + word-wrap: break-word; } + #announce2 a:hover { + text-decoration: underline; } + #announce2 h4 { + color:#3b5998; + font-weight:bold; + text-align: center; + font-size: 13px; + border-bottom: solid 1px #D8DFEA; + padding: 0px 0px 3px; + margin: 5px 5px 3px; } + #announce2 h3 { + text-align: center; + margin: 4px 5px 3px; + color: black; + font-weight: bold; } + +#announce { + width: 120px; + font-size: 11px; } + + #announce div.advert { + margin: 0px auto; + display: block; + line-height: 14px; + background: #f9f9f9; + border: solid 1px #D8DFEA; + border-bottom: solid 1px #3B5998; + margin: 0px 0px 7px; + padding: 1px 0px 2px; } + #announce div.clickable { + cursor: pointer; } + #announce p { + margin: 0px 0px 3px 5px; + overflow: hidden; + width: 110px; + color: #222222; + word-wrap: break-word; } + #announce a:hover { + text-decoration: underline; } + #announce h4 { + color:#3b5998; + font-weight:bold; + text-align: center; + font-size: 13px; + border-bottom: solid 1px #D8DFEA; + padding: 0px 0px 3px; + margin: 5px 5px 3px; } + #announce h3 { + text-align: center; + margin: 4px 5px 3px; + color: black; + font-weight: bold; } + .credit { + text-align: center; } + .create { + text-align: center; + background: #f7f7f7; + border: solid 1px #D8DFEA; + padding: 4px 0px; } + .seeall { + margin: 5px 0px; + text-align: right; } + +#homelink { + float: left; + height: 33px; + line-height: 33px; + width: 250px; + position: absolute; } + +#homelink a { + display: block; + height: 33px; + text-indent: -9999px; } + +#homelink a:hover { + text-decoration: none; } + +#nav { + list-style: none; + margin: 0px; + padding: 1.0em 0px; } + +#nav li { + border-bottom: 1px solid #d8dfea; + font-size: 1.0em; } + +#nav li#myprofile { + border-bottom: 0; } + +#nav li#myfriends { + clear: left; } + +#nav li a { + background: #eee; + background: white; + border-bottom: 1px solid green; + border: 0; + display: block; + padding: 2px 3px; } + +#nav li#myprofile a { + border-bottom: 1px solid #d8dfea; + padding: 0; + width: auto; } + +#nav li#myprofile a.hasedit { + float: left; + padding: 2px 0px 2px 3px; + width: 69px; } + +#nav li#myprofile a.edit { + color: gray; + float: right; + padding: 2px 0; + text-align: center; + width: 48px; } + +#nav li a:hover, +#nav li#myprofile a:hover { + background: #3b5998; + color: white; } + +#fnav { + font-size: 11px; + list-style: none; + margin: 0; + padding: 0; + text-align: center; } + +#fnav li { + display: inline; } + +#fnav li a { + padding: 2px 5px; } + +#fnav li a:hover { + color: white; + background: #3b5998; } + +.wbr { display: block; float:left; } + +/* for boxing long referral/invite links on the home.php right nav bar */ +.html_box { + background: #f7f7f7; + padding: 5px; + margin-top: 10px; + width: 170px; +} + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=share_icon_small.gif +Content-Type: image/gif; name=share_icon_small.gif +Content-Location: http://static.ak.facebook.com/images/share_icon_small.gif +Content-Transfer-Encoding: Base64 + +R0lGODlhCwAsAPcAADtZmKWz0Ozv9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAACwAAAAACwAsAAAIWgADCBhIsKDAgggPIiSocKGAhgshJnTI +kOJAiQYtPtSIsaLFjhc5ivw4kmJDAAAyEkSpEqXLlBsFvGQZcyDNkCth4jRZ0iHI +mj57RhQ6kaRRnkeDJh26tCjFgAA7 +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=share_icon.gif +Content-Type: image/gif; name=share_icon.gif +Content-Location: http://static.ak.facebook.com/images/share_icon.gif +Content-Transfer-Encoding: Base64 + +R0lGODlhDwAsAPcAADtZmKWz0Ozv9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAACwAAAAADwAsAAAIaQADCBhIsGBBgQYTDkSo0CDDhgQfQhQg +EWLFhhcVZky40eHEgx8jhlw4kmLJjiBHohRpEAAAjgldwmz50uNAlzhxshSQM+dO +gjJtFgyacmjNoh9XklR5sinTpyGVmoSa1GlUq1WpTpQaEAA7 +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=share_icon_hover.gif +Content-Type: image/gif; name=share_icon_hover.gif +Content-Location: http://static.ak.facebook.com/images/share_icon_hover.gif +Content-Transfer-Encoding: Base64 + +R0lGODlhDwAsAPcAAHaLt////09qowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAACwAAAAADwAsAAAIaQABCBhIsGBBgQYTDkSo0CDDhgQfQhQg +EWLFhhcVZky40eHEgx8jhlw4kmLJjiBHohRpMEAAjgldwmz50uNAlzhxshSQM+dO +gjJtFgyacmjNoh9XklR5sinTpyGVmoSa1GlUq1WpTpQaEAA7 +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=tour_arrow.gif +Content-Type: image/gif; name=tour_arrow.gif +Content-Location: http://static.ak.facebook.com/images/sitetour/tour_arrow.gif +Content-Transfer-Encoding: Base64 + +R0lGODlhBgANAKIGAGR7rGF5q0hknlpzqERgnDtZmP///wAAACH5BAEAAAYALAAA +AAAGAA0AAAMXaLqwWsMVuCY1luYSMsHTB4oYaQhOqiQAOw== + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=facebookpro.css +Content-Type: text/css; name=facebookpro.css +Content-Location: http://static.ak.facebook.com/css/facebookpro.css?6:37391 +Content-Transfer-Encoding: 8bit + + +.two_column .right, +.two_column .left { + float: left; } + +.no_padding { + padding: 0px; } + +.see_all { + text-align: right; } + +.tab_bar { + padding: 3px 10px 0px; + border-bottom: solid 1px #3B5998; } + + .tab_bar #tabs { + display: inline; + float: left; + border-bottom: none; + margin: 0px; } + + .tab_bar .back_links { + padding: 4px 0px; + float: right; } + +.summary_bar { + position: relative; + color: #3B5998; + font-weight: bold; + padding: 10px 10px 0px; + border-bottom: solid 1px #D8DFEA; } + + .summary_bar h4 { margin: 0px; float: left; } + .summary_bar .pager { float: right; } + + .footer_bar .pager { float: right; } + + +/* ----------------------------| ERROR PAGE |---------------------------- */ + +.error_page #content { + padding: 20px; } + +.error_page #error { + margin: 0px; } + + +/* -----------------------------| PAGER PRO |---------------------------- */ + +.pagerpro { + float: right; + list-style: none; + margin: 0; + padding: 0; +} + +.pagerpro li { + display: inline; + float: left; +} + +.pagerpro a { + border-bottom: 2px solid white; + display: block; + padding: 3px; + padding-bottom: 2px; + text-transform: lowercase; +} +.pagerpro a:hover { + background: #3B5998; + border-color: #D8DFEA; + border-bottom: 1px solid #3B5998; + color: white; + text-decoration: none; +} +.pagerpro .current a, +.pagerpro .current a:hover { + background: transparent; + border-color: #3B5998; + border-bottom: 2px solid #3B5998; + color: #3B5998; + font-weight: bold; + padding-left: 2px; + padding-right: 2px; +} + +.footer_bar .pagerpro a { + border-top: 2px solid white; + padding-top: 1px; + padding-bottom: 0px; +} +.footer_bar .pagerpro a:hover { + border-bottom: 2px solid #3B5998; + border-top: 2px solid #3B5998; +} +.footer_bar .pagerpro .current a, +.footer_bar .pagerpro .current a:hover { + border-bottom-color: white; + border-top: 2px solid #3B5998; +} + +/* ------------------------| TRANSITIONAL STYLES |----------------------- */ + +.summary_bar { + border-bottom: 1px solid #D8DFEA; + clear: both; + padding: 11px 10px 0px 10px; + color: black; + font-weight: normal; + line-height: normal; +} + +.summary_bar .summary { + color: #3B5998; + float: left; + font-weight: bold; + padding-top: 3px; + padding-bottom: 4px; +} + +/*.footer_bar { + float:right; + border-top: 1px solid #D8DFEA; +}*/ +.footer_bar { +border-top:1px solid #D8DFEA; +padding:0pt 10px; +} + +.footer_bar .post_editor { + padding-bottom: 13px; + padding-top: 13px; +} + +.thread .footer_bar .pagerpro a { + border-top: 2px solid #f7f7f7; +} + +.thread .footer_bar .pagerpro a:hover, +.thread .footer_bar .pagerpro .current a, +.thread .footer_bar .pagerpro .current a:hover { + border-top: 2px solid #3B5998; +} + +/* ---------------------------| ACTIONS PRO |---------------------------- */ + +.actionspro { + list-style: none; + margin: 0px; + padding: 0px; } + +.actionspro li { border-bottom: 1px solid #D8DFEA; } + +.actionspro a { + background: transparent; + display: block; + margin: 0px; + padding: 2px 3px; + text-decoration: none; } + +.actionspro a:hover { + background: #3b5998; + color: white; + text-decoration: none; } + +.actionspro .inactive { + background: transparent; + display: block; + margin: 0px; + padding: 2px 3px; + color: #666; +} + +/* ---------------------------| SHARE | HIDE |--------------------------- */ + +.share_and_hide { + font-size: 9px; } + + .s_and_h_big { + font-size: 11px; } + + .share_and_hide a { + padding: 0px 14px 1px 4px; + display: block; + float: left; + background: white url(/images/share_icon_small.gif) repeat-y right center; + border: solid 1px #7f93bc; } + + .s_and_h_big a { + background: white url(/images/share_icon.gif) repeat-y right center; + padding: 1px 18px 2px 4px; } + + .share_and_hide a.save { + background: #eceff5; + border-left: none; } + + .share_and_hide a.with_share { + border: solid 1px #adbad4; + border-left: none; } + + .share_and_hide a:hover { + color: #fff; + border-color: #3B5998; + text-decoration: none; + background: #3B5998 url(/images/share_icon_small_hover.gif) repeat-y right center; } + + .s_and_h_big a:hover { + background: #3B5998 url(/images/share_icon_hover.gif) repeat-y right center; } + + .share_and_hide a.x_to_hide { + border: none; + width: 3px; + padding: 1px 5px 2px; + margin-left: 3px; + background: transparent url(/images/x_to_hide.gif) no-repeat center center; } + + .s_and_h_big a.x_to_hide { + padding: 2px 5px 3px; } + + .share_and_hide a.x_to_hide:hover { + background: #3B5998 url(/images/x_to_hide_hover.gif) no-repeat center center; } + +/* ----------------------------| MISCELLANY |---------------------------- */ + +.boxpro h2 { + background: #d8dfea; + border-top: 1px solid #3b5998; + color: #3b5998; + font-weight: bold; + padding: 2px 8px; +} + +.boxpro .box_icon { + float: left; + padding: 10px; +} + +.boxpro .box_message { + float: left; + padding: 10px; +} + +.quail { + color: #3B5998; + float: left; + padding: 3px 0; } + +.quail a:hover { cursor: text; text-decoration: none } + +/* ------------------------------------------------------------------------ + Facebook | Auxiliary Styles + ------------------------------------------------------------------------ */ + +#pagefooter { border: 0px } + + +/* Migrating classes from <#pagebody> to <body> -------------------------- */ + + +/* friends.css */ + +.friends #content { padding: 0px } + +#pagebody.confirminvite #content { background: white } + +/* mailbox.css */ + +.mailbox #content { padding-bottom: 0px } + + +/* groups.css */ + +.grouplist #content { padding: 0px } + +/* party.css */ + +.partylist #content { padding: 0px } + +/* photos.css */ + +.photos #content, +.album #content, +.photo #content, +.editalbum #content { + position: relative; + margin: 0px; + padding: 0px; } + +.editalbum #content { + padding: 10px 0px 0px; + position: static; } + +.editphoto #content { + padding: 0px; + position: static; } + +.photo #content { position: static } + +.photo #subheader h2 a { font-weight: normal } + +/* places.css */ + +.myplaces #content { + margin: 0px; + padding: 0px; } + +/* profile.css */ + +.profile #content { padding: 10px 0px 10px 10px } + +.wall #content { padding: 10px 0px 0px 0px } + +h4 .edit {} + +/* search.css */ + +.results #content { padding: 0px 0px 0px } + +.results .info { padding-right: 10px } + +/* wall.css */ +.wall #content { + margin: 0px; + padding: 0px; } + + +/* -------------------------| EDIT EVENT INFO |-------------------------- */ + +.eventedit #frm { margin-top: 10px } + +.eventedit select#type { + margin-right: 5px; + width: 150px; } + +.eventedit select#sub_type { + margin-right: 5px; + width: 190px; } + +.eventoption { padding: 0 0 5px 0; } + +/* ------------------------| GROUP ADMIN PAGES |------------------------- */ + +.newgroupadmin #content { + padding-left: 20px; + padding-right: 20px; } + +.newgroupadmin #tabs { + margin-left: 0; + margin-right: 0; } + +.newgroupadmin #error { + margin-left: 0; + margin-right: 0; } + +.pulseblurb td { + padding: 10px 5px; + text-align: left; } + +/* --------------------------| SQUARE BULLETS |-------------------------- */ + +ul.square_bullets { + list-style: square; + padding-left: 20px; + color: #3B5998; } + +ul.square_bullets li { + padding: 1px 0px; } + +ul.square_bullets li span { + color: black; } + + +/* ------------------------| INTERNAL SHARES PAGE |------------------------ */ + +.share_panel { + margin-bottom: -5px; + position: absolute; + z-index: 98; + display: block;} + +.share_internal_popup { + background: white; + border: 10px solid #d8dfea; + display: block; + left: 50px; + position: relative; + top: 20px; + width: 500px; + height: 200px; + z-index: 99; } + +.share_border { + border: 1px solid #3b5998; + height: 178px; + padding: 10px; } + + +/* ----------------------------| MISCELLANY |---------------------------- */ + +/* safari won't do word break in a table without a nested div with a fixed + * width. firefox does not understand break-word at all yet, though it is + * standard css3. */ +.datawrap { word-wrap: break-word; } + +/* this makes opera respect wbr tags. */ +/* firefox and ie already do. */ +/* opera likes ­, but that causes other problems on other browsers. */ +/* safari is clueles about both. */ +wbr:after { content: "\00200B" } + +.jobs #faqindex li { list-style: square } + +/* adjustImage goodness */ +.img_loading { + width: 0px; + height: 0px; +} + +.img_ready { + width: auto; + height: auto; +} + + +/* -----------------------| WELCOME BUTTONS |--------------------------- */ + +.welcome_buttons { + display:block; + padding:8px 0 0 0; + /* padding: 8px 0 0 68px; */ +} + +.welcome_buttons a { + float:left; + display:block; + width:170px; + /* width:200px; */ + padding:5px; + margin-bottom:5px; + color:#666; + background-color:#f7f7f7; + margin-right:12px; + /* margin-right:10px; */ + border-top:1px solid #ccc; + border-bottom:1px solid #ccc; +} + +html #content .welcome_buttons a:hover { + text-decoration:none; + color:#333; + background:#d8dfea; + border-top:1px solid #3b5998; + border-bottom:1px solid #3b5998; +} + +.welcome_buttons a h4 { + margin:0; + padding:0 0 0 14px; + font-size:13px; + color:#333; + background:transparent url(../images/sitetour/tour_arrow.gif) no-repeat 3px 2px; + border: 0px; +} + +.welcome_buttons a:hover h4 { + color:#000; +} + +.welcome_buttons a p { + font-size:11px; + margin:0; + padding:3px 0 2px 14px; +} + +.welcome_buttons a p span { + display:block; +} + +.under_login_tour { + padding:3px 0 0 0; +} + +.under_login_tour a { + width:112px; + padding:3px 4px 4px 4px; + margin:8px 0 0 0; +} + +html #book .under_login_tour a:hover { + text-decoration:none; + color:#333; + background:#d8dfea; + border-top:1px solid #3b5998; + border-bottom:1px solid #3b5998; +} + + +.under_login_tour a h4 { + font-size:11px; + padding:0 0 0 9px; + background:transparent url(../images/sitetour/tour_arrow_micro.gif) no-repeat 2px 4px; +} + +.under_login_tour a p { + font-size:9px; + padding:3px 0 0 9px; +} + +.new_feature_tag { + padding: 3px 0 0 6px; + background: url("/images/new_feature_tag.gif") no-repeat; + height: 14px; + float: left; + margin-right: 6px; + width: 32px; +} + +.new_feature_tag div { + font-size: 9px; + color: #fff; +} + +.new_feature_tag_title { + padding-top: 1px; + margin-bottom: 3px; + font-weight: bold; +} + + +/* Here, take it. It's a goodbye gift. Go clean. ------------------------- */ + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=nonproduct.css +Content-Type: text/css; name=nonproduct.css +Content-Location: http://static.ak.facebook.com/css/nonproduct.css?6:26792 +Content-Transfer-Encoding: 8bit + +/* policy.php, terms.php, some FAQs */ + +.policy #content { padding-top: 5px; } +.policy .wrapper { + line-height: 160%; + padding: 0px 20px 15px; } + +.policy #content h2 { + border-bottom: 1px solid #D8DFEA; + color: #3B5998; + font-size: 14px; + padding-bottom: 5px; } + +.policy #content h3 { + border-bottom: 1px dotted #D8DFEA; + color: #3B5998; + font-size: 12px; + font-weight: bold; + padding-bottom: 5px; + margin-bottom: 5px; } + +.policy #content h4, { + color: #3B5998; + font-size: 11px; + font-weight: bold; + margin: 0 0 5px 0; + padding: 0 0 5px 0; + } + +.policy #content h2 { margin-top: 20px; } + +.policy #content dl { + padding-left: 0px; } + +.policy #content dt { + font-size: 12px; + font-weight: bold; + margin: 0 0 3px; } + +.policy #content dd { + margin: 0 0 10px 10px; } + +.policy #content ol { + padding-left: 25px; } + +/* -----| Jobs Page |---------------------------------------------------- */ + +.jobs .wrapper h2 { + border-bottom: 1px solid #D8DFEA; + color: #3B5998; + font-size: 14px; + padding-bottom: 5px; + } + +.jobs .wrapper h3 { + border-bottom: 1px solid #D8DFEA; + color: #3B5998; + font-size: 12px; + font-weight: bold; + padding-bottom: 3px; + margin-bottom: 5px; + } + +.jobs .wrapper ul.list { margin: 0 0 15px; padding: 0; list-style: none; } +.jobs .wrapper ul.list li { margin: 0 0 3px; } + +.jobs .wrapper h4 { + border-bottom: 1px solid #D8DFEA; + color: #3B5998; + font-size: 12px; + font-weight: bold; + margin: 0; + padding: 0; + padding-bottom: 5px; + margin-bottom: 5px; + } + +.jobs #content { padding: 5px 0 0 0; } +.jobs .wrapper { padding: 0 20px 10px; line-height: 1.5em; } +.jobs .gray { padding-top: 20px; border-top: 1px solid #ccc; background: #f7f7f7; } + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=jobs_engineering.css +Content-Type: text/css; name=jobs_engineering.css +Content-Location: http://static.ak.facebook.com/css/jobs_engineering.css?6:35282 +Content-Transfer-Encoding: 8bit + +.jobs .column { + float: left; } + +.jobs .text_column { + width: 550px; } + +/* ---| MAIN COLUMN |----------------------------------------------------- */ + +.jobs .pics_column { + margin-top: 20px; + width: 76px; } + +.jobs img { + border: 1px solid #c0c0c0; + padding: 2px; + margin: 0 6px 2px 0; +} + +.jobs img.right { + margin: 0 0 2px 6px; +} + +.jobs img:hover { + border-color: #3B5998; +} + +.jobs .puzcode { + padding: 5px; + border-style: solid; + border-width: 1px; + border-color: lightgrey; + margin: 10px 20px 10px 20px; + background-color: #eeeeee; +} + +------------baYQE7JahMjuMBxFf0oq6T +Content-Disposition: inline; filename=base.js +Content-Type: application/x-javascript; name=base.js +Content-Location: http://static.ak.facebook.com/js/base.js?6:35674 +Content-Transfer-Encoding: Base64 + +Ci8vID09PSBHZXQvSGlkZS9TaG93L1RvZ2dsZSA9PT0KCmZ1bmN0aW9uIGdlKCkK +ewogIHZhciBlYTsKICBmb3IoIHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5n +dGg7IGkrKyApIHsKICAgIHZhciBlID0gYXJndW1lbnRzW2ldOwogICAgaWYoIHR5 +cGVvZiBlID09ICdzdHJpbmcnICkKICAgICAgZSA9IGRvY3VtZW50LmdldEVsZW1l +bnRCeUlkKGUpOwogICAgaWYoIGFyZ3VtZW50cy5sZW5ndGggPT0gMSApCiAgICAg +IHJldHVybiBlOwogICAgaWYoICFlYSApCiAgICAgIGVhID0gbmV3IEFycmF5KCk7 +CiAgICBlYVtlYS5sZW5ndGhdID0gZTsKICB9CiAgcmV0dXJuIGVhOwp9CgpmdW5j +dGlvbiBzaG93KCkKewogIGZvciggdmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxl +bmd0aDsgaSsrICkgewogICAgdmFyIGVsZW1lbnQgPSBnZShhcmd1bWVudHNbaV0p +OwogICAgaWYgKGVsZW1lbnQgJiYgZWxlbWVudC5zdHlsZSkgZWxlbWVudC5zdHls +ZS5kaXNwbGF5ID0gJyc7CiAgfQogIHJldHVybiBmYWxzZTsKfQoKZnVuY3Rpb24g +aGlkZSgpCnsKICBmb3IoIHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7 +IGkrKyApIHsKICAgIHZhciBlbGVtZW50ID0gZ2UoYXJndW1lbnRzW2ldKTsKICAg +IGlmIChlbGVtZW50ICYmIGVsZW1lbnQuc3R5bGUpIGVsZW1lbnQuc3R5bGUuZGlz +cGxheSA9ICdub25lJzsKICB9CiAgcmV0dXJuIGZhbHNlOwp9CgpmdW5jdGlvbiBz +aG93bihlbCkgewogICAgZWwgPSBnZShlbCk7CiAgICByZXR1cm4gKGVsLnN0eWxl +LmRpc3BsYXkgIT0gJ25vbmUnKTsKfQoKZnVuY3Rpb24gdG9nZ2xlKCkKewogIGZv +ciggdmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrICkgewogICAg +dmFyIGVsZW1lbnQgPSBnZShhcmd1bWVudHNbaV0pOwogICAgZWxlbWVudC5zdHls +ZS5kaXNwbGF5ID0gKGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9PSAnYmxvY2snKSA/ +ICdub25lJyA6ICdibG9jayc7CiAgfQogIHJldHVybiBmYWxzZTsKfQoKZnVuY3Rp +b24gcmVtb3ZlX25vZGUobm9kZSkKewogIGlmIChub2RlLnJlbW92ZU5vZGUpCiAg +ICBub2RlLnJlbW92ZU5vZGUodHJ1ZSk7CiAgZWxzZSB7CiAgICBmb3IgKHZhciBp +PW5vZGUuY2hpbGROb2Rlcy5sZW5ndGgtMTsgaT49MDsgaS0tKQogICAgICByZW1v +dmVfbm9kZShub2RlLmNoaWxkTm9kZXNbaV0pOwogICAgICBub2RlLnBhcmVudE5v +ZGUucmVtb3ZlQ2hpbGQobm9kZSk7CiAgICB9CiAgcmV0dXJuIG51bGw7Cn0KCi8v +ID09PSBFdmVudCBJbmZvIEFjY2VzcyA9PT0KCmZ1bmN0aW9uIG1vdXNlWChldmVu +dCkKewogIHJldHVybiBldmVudC5wYWdlWCB8fCAoZXZlbnQuY2xpZW50WCArCiAg +ICAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgfHwgZG9jdW1l +bnQuYm9keS5zY3JvbGxMZWZ0KSk7Cn0KCmZ1bmN0aW9uIG1vdXNlWShldmVudCkK +ewogIHJldHVybiBldmVudC5wYWdlWSB8fCAoZXZlbnQuY2xpZW50WSArCiAgICAo +ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCB8fCBkb2N1bWVudC5i +b2R5LnNjcm9sbFRvcCkpOwp9CgpmdW5jdGlvbiBwYWdlU2Nyb2xsWCgpCnsKICBy +ZXR1cm4gZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0IHx8IGRvY3VtZW50LmRvY3Vt +ZW50RWxlbWVudC5zY3JvbGxMZWZ0Owp9CgpmdW5jdGlvbiBwYWdlU2Nyb2xsWSgp +CnsKICByZXR1cm4gZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgfHwgZG9jdW1lbnQu +ZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcDsKfQoKZnVuY3Rpb24gZWxlbWVudFgo +b2JqKQp7CiAgdmFyIGN1cmxlZnQgPSAwOwogIGlmIChvYmoub2Zmc2V0UGFyZW50 +KSB7CiAgICB3aGlsZSAob2JqLm9mZnNldFBhcmVudCkgewogICAgICBjdXJsZWZ0 +ICs9IG9iai5vZmZzZXRMZWZ0OwogICAgICBvYmogPSBvYmoub2Zmc2V0UGFyZW50 +OwogICAgfQogIH0KICBlbHNlIGlmIChvYmoueCkKICAgIGN1cmxlZnQgKz0gb2Jq +Lng7CiAgcmV0dXJuIGN1cmxlZnQ7Cn0KCmZ1bmN0aW9uIGVsZW1lbnRZKG9iaikK +ewogIHZhciBjdXJ0b3AgPSAwOwogIGlmKG9iai5vZmZzZXRQYXJlbnQpIHsKICAg +IHdoaWxlIChvYmoub2Zmc2V0UGFyZW50KSB7CiAgICAgIGN1cnRvcCArPSBvYmou +b2Zmc2V0VG9wOwogICAgICBvYmogPSBvYmoub2Zmc2V0UGFyZW50OwogICAgfQog +IH0KICBlbHNlIGlmIChvYmoueSkKICAgIGN1cnRvcCArPSBvYmoueTsKICByZXR1 +cm4gY3VydG9wOwp9CgovLyA9PT0gT25sb2FkIFJlZ2lzdHJ5ID09PQoKZnVuY3Rp +b24gb25sb2FkUmVnaXN0ZXIoaGFuZGxlcikgewogIGlmICh3aW5kb3cub25sb2Fk +KSB7CiAgICB2YXIgb2xkPXdpbmRvdy5vbmxvYWQ7CiAgICB3aW5kb3cub25sb2Fk +PWZ1bmN0aW9uKCkgeyBvbGQoKTsgaGFuZGxlcigpOyB9OwogIH0KICBlbHNlIHsK +ICAgIHdpbmRvdy5vbmxvYWQ9aGFuZGxlcjsKICB9Cn0KCi8vID09PSBQbGFjZWhv +bGRlciBUZXh0ID09PQoKZnVuY3Rpb24gcGxhY2Vob2xkZXJTZXR1cChpZCkgewog +IHZhciBlbCA9IGdlKGlkKTsKICBpZighZWwpIHJldHVybjsKICAvKmlmKGVsLnR5 +cGUgIT0gJ3RleHQnKSByZXR1cm47Ki8KICAKICB2YXIgcGggPSBlbC5nZXRBdHRy +aWJ1dGUoInBsYWNlaG9sZGVyIik7CiAgaWYoIHBoICYmIHBoICE9ICIiICkgewog +ICAgZWwudmFsdWUgPSBwaDsKICAgIGVsLnN0eWxlLmNvbG9yID0gJyM3NzcnOwog +ICAgZWwuaXNfZm9jdXNlZCA9IDA7CiAgICBlbC5vbmZvY3VzID0gcGxhY2Vob2xk +ZXJGb2N1czsKICAgIGVsLm9uYmx1ciA9IHBsYWNlaG9sZGVyQmx1cjsKICB9Cn0K +CmZ1bmN0aW9uIHBsYWNlaG9sZGVyRm9jdXMoKSB7CiAgaWYoIXRoaXMuaXNfZm9j +dXNlZCkgewogICAgdGhpcy5pc19mb2N1c2VkID0gMTsKICAgIHRoaXMudmFsdWUg +PSAnJzsKICAgIHRoaXMuc3R5bGUuY29sb3IgPSAnIzAwMCc7CgogICAgdmFyIHJz +ID0gdGhpcy5nZXRBdHRyaWJ1dGUoInJhZGlvc2VsZWN0Iik7CiAgICBpZiggcnMg +JiYgcnMgIT0gIiIgKSB7CiAgICAgIHZhciByZSA9IGRvY3VtZW50LmdldEVsZW1l +bnRCeUlkKHJzKTsKICAgICAgaWYoIXJlKSB7IHJldHVybjsgfQogICAgICBpZihy +ZS50eXBlICE9ICdyYWRpbycpIHJldHVybjsKCiAgICAgIHJlLmNoZWNrZWQ9dHJ1 +ZTsKICAgIH0KICB9Cn0KCmZ1bmN0aW9uIHBsYWNlaG9sZGVyQmx1cigpIHsKICB2 +YXIgcGggPSB0aGlzLmdldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiKQogIGlmKCB0 +aGlzLmlzX2ZvY3VzZWQgJiYgcGggJiYgdGhpcy52YWx1ZSA9PSAiIiApIHsKICAg +IHRoaXMuaXNfZm9jdXNlZCA9IDA7CiAgICB0aGlzLnZhbHVlID0gcGg7CiAgICB0 +aGlzLnN0eWxlLmNvbG9yID0gJyM3NzcnOwogIH0KfQoKLy8gPT09IFN0cmluZyBV +dGlsaXRpZXMgPT09CgpmdW5jdGlvbiBodG1sc3BlY2lhbGNoYXJzKHRleHQpIHsK +ICByZXR1cm4gdGV4dCA/IHRleHQudG9TdHJpbmcoKS5yZXBsYWNlKC8mL2csICcm +YW1wOycpLnJlcGxhY2UoLyIvZywgJyZxdW90OycpLnJlcGxhY2UoLycvZywgJyYj +MDM5OycpLnJlcGxhY2UoLzwvZywgJyZsdDsnKS5yZXBsYWNlKC8+L2csICcmZ3Q7 +JykgOiAnJzsKfQoKZnVuY3Rpb24gZXNjYXBlX2pzX3F1b3Rlcyh0ZXh0KSB7CiAg +aWYgKCF0ZXh0KSB7CiAgICByZXR1cm47CiAgfQoKICByZXR1cm4gdGV4dC5yZXBs +YWNlKC9cXC9nLCAnXFxcXCcpLnJlcGxhY2UoL1xuL2csICdcXG4nKS5yZXBsYWNl +KC9cci9nLCAnXFxyJykucmVwbGFjZSgvIi9nLCAnXFx4MjInKS5yZXBsYWNlKC8n +L2csICdcXFwnJykucmVwbGFjZSgvPC9nLCAnXFx4M2MnKS5yZXBsYWNlKC8+L2cs +ICdcXHgzZScpLnJlcGxhY2UoLyYvZywgJ1xceDI2Jyk7Cn0KCmZ1bmN0aW9uIHRy +aW0oc3RyKSB7CiAgdmFyIGRlbGltID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBh +cmd1bWVudHNbMV0gOiAnICc7CiAgZm9yICh2YXIgaT0wLCBjPXN0ci5sZW5ndGgt +ZGVsaW0ubGVuZ3RoOyBpPD1jOyBpKz1kZWxpbS5sZW5ndGgpIHsKICAgIGlmIChz +dHIuc3Vic3RyaW5nKGksIGkgKyBkZWxpbS5sZW5ndGgpICE9IGRlbGltKSB7CiAg +ICAgIGJyZWFrOwogICAgfQogIH0KCiAgZm9yICh2YXIgaj1zdHIubGVuZ3RoLCBj +PU1hdGgubWF4KGksIGRlbGltLmxlbmd0aCAtIDEpOyBqPmM7IGotPWRlbGltLmxl +bmd0aCkgewogICAgaWYgKHN0ci5zdWJzdHJpbmcoaiAtIGRlbGltLmxlbmd0aCwg +aikgIT0gZGVsaW0pIHsKICAgICAgYnJlYWs7CiAgICB9CiAgfQoKICByZXR1cm4g +c3RyLnN1YnN0cmluZyhpLCBqKTsKfQoKLy8gPT09IFVSSSBIYW5kbGluZyA9PT0K +CmZ1bmN0aW9uIGVzY2FwZVVSSSh1KQp7CiAgICBpZihlbmNvZGVVUklDb21wb25l +bnQpIHsKICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHUpOwogICAg +fQogICAgaWYoZXNjYXBlKSB7CiAgICAgICAgcmV0dXJuIGVzY2FwZSh1KTsKICAg +IH0KfQoKZnVuY3Rpb24gZ29VUkkoaHJlZikgewogIHdpbmRvdy5sb2NhdGlvbi5o +cmVmID0gaHJlZjsKfQoKZnVuY3Rpb24gaXNfZW1haWwoZW1haWwpIHsKICByZXR1 +cm4gL15bXHchLiUrXStAW1x3XSsoPzpcLltcd10rKSskLy50ZXN0KGVtYWlsKTsK +fQoKLy8xM3RoIHBhcmFsbGVsCmZ1bmN0aW9uIGdldFZpZXdwb3J0V2lkdGgoKSB7 +CiAgdmFyIHdpZHRoID0gMDsKICBpZiggZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50 +ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCApIHsKICAg +IHdpZHRoID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoOwog +IH0KICBlbHNlIGlmKCBkb2N1bWVudC5ib2R5ICYmIGRvY3VtZW50LmJvZHkuY2xp +ZW50V2lkdGggKSB7CiAgICB3aWR0aCA9IGRvY3VtZW50LmJvZHkuY2xpZW50V2lk +dGg7CiAgfQogIGVsc2UgaWYoIHdpbmRvdy5pbm5lcldpZHRoICkgewogICAgd2lk +dGggPSB3aW5kb3cuaW5uZXJXaWR0aCAtIDE4OwogIH0KICByZXR1cm4gd2lkdGg7 +Cn07CgpmdW5jdGlvbiBnZXRWaWV3cG9ydEhlaWdodCgpIHsKICB2YXIgaGVpZ2h0 +ID0gMDsKICBpZiggZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmIGRvY3VtZW50 +LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQgKSB7CiAgICBoZWlnaHQgPSBk +b2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0OwogIH0KICBlbHNl +IGlmKCBkb2N1bWVudC5ib2R5ICYmIGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0 +ICkgewogICAgaGVpZ2h0ID0gZG9jdW1lbnQuYm9keS5jbGllbnRIZWlnaHQ7CiAg +fQogIGVsc2Uga... [truncated message content] |
From: <yan...@us...> - 2009-05-25 18:22:26
|
Revision: 1431 http://assorted.svn.sourceforge.net/assorted/?rev=1431&view=rev Author: yangzhang Date: 2009-05-25 18:22:18 +0000 (Mon, 25 May 2009) Log Message: ----------- dumping some more old code here Added Paths: ----------- auto-mirror/trunk/README auto-mirror/trunk/src/Main.hs auto-mirror/trunk/src/Makefile auto-mirror/trunk/src/download.bash Added: auto-mirror/trunk/README =================================================================== --- auto-mirror/trunk/README (rev 0) +++ auto-mirror/trunk/README 2009-05-25 18:22:18 UTC (rev 1431) @@ -0,0 +1,2 @@ +This was originally used in the CarTel project, but I thought it might be +useful on its own. Added: auto-mirror/trunk/src/Main.hs =================================================================== --- auto-mirror/trunk/src/Main.hs (rev 0) +++ auto-mirror/trunk/src/Main.hs 2009-05-25 18:22:18 UTC (rev 1431) @@ -0,0 +1,241 @@ +module Main where + +{- + +To follow up on my previous post ("Asynchronous Exceptions and the +RealWorld"), I've decided to put together something more concrete in +the hopes of eliciting response. + +I'm trying to write a library of higher-level concurrency +abstractions, in particular for asynchronous systems programming. + +There are a number of immediate goals: + +- Composability and safety (intentionally vague). + +- Currently, the focus is on building synchronous combinators + (asynchronous primitives for later). + +- Ideally, be able to apply combinators on any existing (IO a), not + just procedures written for this library. + +Below, the running theme is process orchestration. (I've put TODOs at +places where I'm blocked.) + +I'm currently worried that what I'm trying to do is impossible in +Concurrent Haskell. I'm bewildered by the design decisions in the +asynchronous exceptions paper. I'm also wondering if there are any +efforts under way to reform this situation. I found some relevant +posts below hinting at this, but I'm not sure what the status is +today. + +(Something like this is straightforward to build if I abandon +Concurrent Haskell and use cooperative threading, and if the +operations I wanted to perform could be done asynchronously.) + +Relevant papers: + +http://citeseer.ist.psu.edu/415348.html +http://research.microsoft.com/users/simonpj/papers/concurrent-haskell.ps.gz +http://www.haskell.org/~simonmar/papers/web-server.ps.gz + +Relevant posts/threads: + +http://osdir.com/ml/lang.haskell.prime/2006-04/msg00032.html +http://osdir.com/ml/lang.haskell.general/2001-11/msg00131.html +http://www.haskell.org/pipermail/haskell-prime/2006-April/001280.html +http://www.haskell.org/pipermail/haskell-prime/2006-April/001290.html +http://www.nabble.com/throwTo---block-statements-considered-harmful-tf2780268.html#a7758038 +http://www.nabble.com/What-guarantees-(if-any)-do-interruptible-operations-have-in-presence-of-asynchronous-exceptions--tf2761696.html#a7699555 + +Misc + +http://lambda-the-ultimate.org/node/1570 +Advanced Exception Handling Mechanisms +http://www.springerlink.com/content/3723wg2t81248027/ +http://64.233.169.104/search?q=cache:c4pS0FDKMXcJ:www.cs.ioc.ee/tfp-icfp-gpce05/tfp-proc/06num.pdf+concurrency+interrupts+abort+safe+asynchronous+exceptions+threads&h +http://64.233.169.104/search?q=cache:hmC-jl-iNkoJ:www.jot.fm/issues/issue_2007_11/article4.pdf+concurrency+interrupts+abort+safe+asynchronous+exceptions+threads&hl=en +http://www.mathematik.uni-marburg.de/~eden/paper/edenEuropar03.pdf + +-} + +import Control.Concurrent +import Control.Concurrent.MVar +import Control.Exception +import Control.Monad +import Prelude hiding (log) +import System.IO +import System.Posix.Signals +import System.Process + +log = putStrLn + +startProc cmd = runCommand cmd +stopProc p = terminateProcess p +waitProc p = waitForProcess p + +-- Run a process, blocking on it until it exits. If we're interrupted, +-- terminate the process. (IIRC, terminateProcess issues SIGTERM, and +-- the documentation is buggy; more detailed code should go here later +-- to retry with SIGKILL.) +runProc cmd = do + log "launching proc" + p <- startProc cmd + waitProc p -- TODO allow interrupts only at this point + `finally` ( log "stopping" >> stopProc p >> log "stopped" ) + +-- Sleep for n seconds. +timeout n = do + log "sleeping" + threadDelay (n * 1000000) -- TODO allow interrupts only at this point + log "waking" + +-- TODO is there any way to block *only* the Cancel exception? (Even +-- if this could be done, though, it's still not a modular approach.) +spawn :: IO a -> (a -> IO ()) -> IO ThreadId +spawn f y = forkIO (block (f >>= y)) + +-- The any/sum/choice combinator. On return, guarantee that both tasks +-- have stopped. +(<|>) :: IO a -> IO b -> IO (Either a b) +a <|> b = do + result <- newEmptyMVar :: IO (MVar (Either a b)) + tida <- newEmptyMVar :: IO (MVar ThreadId) + tidb <- newEmptyMVar :: IO (MVar ThreadId) + + let yield lr x = do let name = case lr x of + Left _ -> "a" + Right _ -> "b" + log $ "saving result of " ++ name + putMVar result (lr x) + log $ "saved result of " ++ name + + let other = case lr x of + Left _ -> tidb + Right _ -> tida + log "taking other" + t <- takeMVar other + log "killing other" + -- Later: replace the following with a throwTo + -- so as to notify (rather than kill) the thread + -- with a Cancel + killThread t + + ta <- spawn a (yield Left) + tb <- spawn b (yield Right) + putMVar tida ta + putMVar tidb tb + + log "waiting for result" + res <- takeMVar result + + -- TODO wait for both tasks to have stopped + + log "returning result" + return res + +-- simple test -- + +cmd1 = "for i in `seq 1`; do sleep 1; echo hello; done" +cmd2 = "for i in `seq 3`; do sleep 1; echo world; done" + +main = do + -- TODO for some reason, the other + result <- runProc cmd1 <|> runProc cmd2 + case result of + Left _ -> putStrLn "finished process" + Right _ -> putStrLn "got exception" + + + + +--- + + + +{- +run cmd = do + forkProcess + executeFile "" + +pollStatus = getProcessStatus False False + +running p = do + status <- pollStatus p + return status == Nothing +-} + +waitSignal sig yield = putStrLn "waitSig" >> + -- installHandler sig Ignore Nothing + installHandler sig (Catch (yield ())) Nothing >> return () + + + + + + +-- cmd = "wget -N -P dldir --no-remove-listing 'ftp://ftpuser:password@128.30.76.78/icedb/*'" +-- cmd = "wget ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/iso/2007.08/x86_64/Archlinux-x86_64-2007.08-2.core.iso" + + +{- + +main = do + tid <- forkIO $ sleepIO -- netIO -- spinIO + threadDelay 1000000 + putStrLn "killing" + killThread tid + +sleepIO = do + threadDelay 10000000 + putStrLn "awake" + +netIO = do + block $ do + h <- connectTo "127.0.0.1" (PortNumber 9876) + putStrLn "connected" + forM_ [1..] $ \_ -> do + hPutStr h "." -- this is not interruptible, yet... + -- hPutStr h $ replicate 8192 '.' -- this is interruptible! + hFlush h + putStrLn "wrote" + s <- hGetContents h + print (length s) + +spinIO = do + block $ do + spin + x <- connectTo "1.1.1.1" (PortNumber 1) + putStrLn "connect done (should not be here)" + +spin = do + print $ length $ map (**2) [1.0 .. 9999999.0] + putStrLn "spin done" + +-} + +{- +import Control.Concurrent +import Network.FTP.Client + +main = do +-- installHandler + tid <- myThreadId + forkIO $ watchdog tid + beta + +watchdog tid = do + threadDelay 1000000 + putStrLn "killing" + killThread tid + +beta = do + enableFTPDebugging + h <- easyConnectFTP "1.1.1.1" -- "ftp.kernel.org" + loginAnon h + cwd h "/pub/linux/kernel/Historic" + nlst h Nothing >>= putStrLn . unlines + getbinary h "linux-0.01.tar.gz.sign" >>= putStrLn . fst + dir h Nothing >>= putStrLn . unlines + quit h +-} \ No newline at end of file Added: auto-mirror/trunk/src/Makefile =================================================================== --- auto-mirror/trunk/src/Makefile (rev 0) +++ auto-mirror/trunk/src/Makefile 2009-05-25 18:22:18 UTC (rev 1431) @@ -0,0 +1,7 @@ +all: Main + +Main: Main.hs + ghc --make -threaded Main.hs + +clean: + rm -f Main Added: auto-mirror/trunk/src/download.bash =================================================================== --- auto-mirror/trunk/src/download.bash (rev 0) +++ auto-mirror/trunk/src/download.bash 2009-05-25 18:22:18 UTC (rev 1431) @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +trap '' USR1 + +set -o errexit +set -o nounset + +url='ftp://ftpuser:password@128.30.76.78/icedb/*' +killed= + +handle() { + echo 'handling sigusr1' $wget + kill $wget + killed=1 +} + +while true ; do + trap '' USR1 + wget -q -N --no-remove-listing -P /dldir "$url" & + wget=$! + trap handle USR1 + wait $wget + break + # trap - USR1 +done + +echo done + +# vim:et:sw=2:ts=2 Property changes on: auto-mirror/trunk/src/download.bash ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 17:28:38
|
Revision: 1430 http://assorted.svn.sourceforge.net/assorted/?rev=1430&view=rev Author: yangzhang Date: 2009-05-25 17:28:28 +0000 (Mon, 25 May 2009) Log Message: ----------- refactored templates/views; tweaked design Modified Paths: -------------- pitch-in/trunk/src/pitchin/pitchin/templates/created.html pitch-in/trunk/src/pitchin/pitchin/templates/main.html pitch-in/trunk/src/pitchin/pitchin/templates/pool.html pitch-in/trunk/src/pitchin/pitchin/views.py pitch-in/trunk/src/pitchin/static/default.css Added Paths: ----------- pitch-in/trunk/src/pitchin/pitchin/templates/base.html Added: pitch-in/trunk/src/pitchin/pitchin/templates/base.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/base.html (rev 0) +++ pitch-in/trunk/src/pitchin/pitchin/templates/base.html 2009-05-25 17:28:28 UTC (rev 1430) @@ -0,0 +1,19 @@ +<html> + <head> + <title>{% block title %}PitchIn{% endblock %}</title> + <link rel="stylesheet" type="text/css" href="static/default.css"/> + </head> + <body> + <div class="box"> + <div class="boxtop"><div></div></div> + <div class="header"> + <img src="static/pitchin.png"/> + </div> + <div class="body"> + {% block body %}{% endblock %} + <small>PitchIn © 2009 <a href="http://www.mit.edu/~y_z/">Yang Zhang</a></small> + </div> + <div class="boxbottom"><div></div></div> + </div> + </body> +</html> Modified: pitch-in/trunk/src/pitchin/pitchin/templates/created.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/created.html 2009-05-25 17:20:56 UTC (rev 1429) +++ pitch-in/trunk/src/pitchin/pitchin/templates/created.html 2009-05-25 17:28:28 UTC (rev 1430) @@ -1,25 +1,11 @@ -<html> - <head> - <title>PitchIn - Pool Successfully Created</title> - <link rel="stylesheet" type="text/css" href="static/default.css"/> - </head> - <body> - <div class="box"> - <div class="boxtop"><div></div></div> - <div class="header"> - <img src="static/pitchin.png"/> - </div> - <div class="body"> - <p> - Congrats! You've successfully created a new money pool. - Send this URL out to anyone you're inviting to - participate: - </p> - <p> - <a href="/pool?key={{key}}">http://pitch-in.appspot.com/pool?key={{key}}</a> - </p> - </div> - <div class="boxbottom"><div></div></div> - </div> - </body> -</html> +{% extends 'base.html' %} +{% block body %} + <p> + Congrats! You've successfully created a new money pool. + Send this URL out to anyone you're inviting to + participate: + </p> + <p> + <a href="/pool?key={{key|urlencode}}">http://pitch-in.appspot.com/pool?key={{key|urlencode}}</a> + </p> +{% endblock %} Modified: pitch-in/trunk/src/pitchin/pitchin/templates/main.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-25 17:20:56 UTC (rev 1429) +++ pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-25 17:28:28 UTC (rev 1430) @@ -1,35 +1,21 @@ -<html> - <head> - <title>PitchIn!</title> - <link rel="stylesheet" type="text/css" href="static/default.css"/> - </head> - <body> - <div class="box"> - <div class="boxtop"><div></div></div> - <div class="header"> - <img src="static/pitchin.png"/> - </div> - <div class="body"> - <p class="line">Easily create and manage a money pool that others can contribute to.</p> - <p> - To create a pool, just enter a description of what it's for here, and you - will be provided a URL that you can distribute to the people you want to - participate in the pool. - </p> - <p class="error">{{error}}</p> - <form action="/create" method="post"> - <div> - <input class="text-input" type="text" name="descrip"/> - <input type="submit" width="50" value="Create Pool"> - </div> - </form> - <div class="example"> - <p style="font-size: larger; font-weight: bold">Example descriptions:</p> - <p>“Birthday gift for Amy (we're aiming for $180 Rock Band set)”</p> - <p>“Holiday vacation trip”</p> - </div> - </div> - <div class="boxbottom"><div></div></div> +{% extends 'base.html' %} +{% block body %} + <p class="line">Easily create and manage a money pool that others can contribute to.</p> + <p> + To create a pool, just enter a description of what it's for here, and you + will be provided a URL that you can distribute to the people you want to + participate in the pool. + </p> + <p class="error">{{error}}</p> + <form action="/create" method="post"> + <div> + <input class="text-input" type="text" name="descrip"/> + <input type="submit" width="50" value="Create Pool"> </div> - </body> -</html> + </form> + <div class="example"> + <p style="font-size: larger; font-weight: bold">Example descriptions:</p> + <p>“Birthday gift for Amy (we're aiming for $180 Rock Band set)”</p> + <p>“Holiday vacation trip”</p> + </div> +{% endblock %} Modified: pitch-in/trunk/src/pitchin/pitchin/templates/pool.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-25 17:20:56 UTC (rev 1429) +++ pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-25 17:28:28 UTC (rev 1430) @@ -1,36 +1,27 @@ -<html> - <head> - <title>PitchIn!</title> - <link rel="stylesheet" type="text/css" href="static/default.css"/> - </head> - <body> - <div class="box"> - <div class="boxtop"><div></div></div> - <div class="header"> - <img src="static/pitchin.png"/> - </div> - <div class="body"> - <p style="font-size: larger"><span style="font-weight: bold">Pool:</span> {{descrip}}</p> - {{contribs}} - <p> - To add or update your own contribution to the pool, enter - the following information. - </p> - <form action="/pool" method="post"> - <p class="error">{{error}}</p> - <input type="hidden" name="key" value="{{key}}"/> - <div> - <label name="name">Name:</label> - <input type="text" name="name"/> - </div> - <div> - <label name="amount">Contribution:</label> - <input type="text" name="amount"/> - </div> - <div><input type="submit" value="Enter the pool!"/></div> - </form> - </div> - <div class="boxbottom"><div></div></div> +{% extends 'base.html' %} +{% block body %} + <p style="font-size: larger"><span style="font-weight: bold">Pool:</span> {{descrip|escape}}</p> + {% for contrib in contribs %} + <div class="row{% cycle 0,1 %}">{{contrib.0|escape}}: {{contrib.1|escape}}</div> + {% endfor %} + {% for contrib in aggcontribs %} + <div class="aggrow">{{contrib.0|escape}}: {{contrib.1|escape}}</div> + {% endfor %} + <p> + To add or update your own contribution to the pool, enter + the following information. + </p> + <form action="/pool" method="post"> + <p class="error">{{error}}</p> + <input type="hidden" name="key" value="{{key|urlencode}}"/> + <div> + <label name="name">Name:</label> + <input type="text" name="name"/> </div> - </body> -</html> + <div> + <label name="amount">Contribution:</label> + <input type="text" name="amount"/> + </div> + <div><input type="submit" value="Enter the pool!"/></div> + </form> +{% endblock %} Modified: pitch-in/trunk/src/pitchin/pitchin/views.py =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-25 17:20:56 UTC (rev 1429) +++ pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-25 17:28:28 UTC (rev 1430) @@ -13,6 +13,8 @@ if len(contribs) == 0: return '<p style="font-style: italic;">(no participants yet)</p>' else: + return contribs.items() , [('Max total', sum(contribs.itervalues())), + ('If everyone paid the minimum', len(contribs) * min(contribs.itervalues()))] s = '<div class="rows">' for i, (name, amount) in enumerate(contribs.iteritems()): s += '<div class="row%d">%s: %d</div>' % (i % 2, cgi.escape(name), amount) @@ -45,8 +47,9 @@ pool = getPool(request) return render_to_response('pool.html', dict(error = error, - descrip = cgi.escape(pool.descrip), - contribs = showContribs(pool), + descrip = pool.descrip, + contribs = showContribs(pool)[0], + aggcontribs = showContribs(pool)[1], key = request.REQUEST['key'])) def update(request): Modified: pitch-in/trunk/src/pitchin/static/default.css =================================================================== --- pitch-in/trunk/src/pitchin/static/default.css 2009-05-25 17:20:56 UTC (rev 1429) +++ pitch-in/trunk/src/pitchin/static/default.css 2009-05-25 17:28:28 UTC (rev 1430) @@ -28,4 +28,4 @@ .row0, .row1, .aggrow { padding-top: 3px; padding-bottom: 3px; } .row0 { background-color: #dddddd; } .row1 { background-color: #eeeeee; } -.aggrow { color: white; background-color: black; font-weight: bold; } +.aggrow { font-weight: bold; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 17:21:24
|
Revision: 1429 http://assorted.svn.sourceforge.net/assorted/?rev=1429&view=rev Author: yangzhang Date: 2009-05-25 17:20:56 +0000 (Mon, 25 May 2009) Log Message: ----------- added readme Added Paths: ----------- pitch-in/trunk/README Added: pitch-in/trunk/README =================================================================== --- pitch-in/trunk/README (rev 0) +++ pitch-in/trunk/README 2009-05-25 17:20:56 UTC (rev 1429) @@ -0,0 +1,5 @@ +Nice new features in Django 1.0: + +- new cycle syntax: cycle '0' '1' +- autoescape +- for key, value in collection This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-25 06:24:55
|
Revision: 1428 http://assorted.svn.sourceforge.net/assorted/?rev=1428&view=rev Author: yangzhang Date: 2009-05-25 06:24:45 +0000 (Mon, 25 May 2009) Log Message: ----------- re-designed for web 2.0 look Modified Paths: -------------- pitch-in/trunk/src/pitchin/app.yaml pitch-in/trunk/src/pitchin/pitchin/templates/created.html pitch-in/trunk/src/pitchin/pitchin/templates/main.html pitch-in/trunk/src/pitchin/pitchin/templates/pool.html pitch-in/trunk/src/pitchin/pitchin/views.py Added Paths: ----------- pitch-in/trunk/src/pitchin/static/ pitch-in/trunk/src/pitchin/static/bl.png pitch-in/trunk/src/pitchin/static/br.png pitch-in/trunk/src/pitchin/static/default.css pitch-in/trunk/src/pitchin/static/pitchin.png pitch-in/trunk/src/pitchin/static/tl.png pitch-in/trunk/src/pitchin/static/tr.png Removed Paths: ------------- pitch-in/trunk/src/pitchin/pitchin/templates/index.html Modified: pitch-in/trunk/src/pitchin/app.yaml =================================================================== --- pitch-in/trunk/src/pitchin/app.yaml 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/app.yaml 2009-05-25 06:24:45 UTC (rev 1428) @@ -4,5 +4,7 @@ api_version: 1 handlers: +- url: /static + static_dir: static - url: /.* script: main.py Modified: pitch-in/trunk/src/pitchin/pitchin/templates/created.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/created.html 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/pitchin/templates/created.html 2009-05-25 06:24:45 UTC (rev 1428) @@ -1,12 +1,25 @@ <html> + <head> + <title>PitchIn - Pool Successfully Created</title> + <link rel="stylesheet" type="text/css" href="static/default.css"/> + </head> <body> - <p> - Congrats! You've successfully created a new money pool. - Send this URL out to anyone you're inviting to - participate: - </p> - <p> - <a href="/pool?key={{key}}">http://pitch-in.appspot.com/pool?key={{key}}</a> - </p> + <div class="box"> + <div class="boxtop"><div></div></div> + <div class="header"> + <img src="static/pitchin.png"/> + </div> + <div class="body"> + <p> + Congrats! You've successfully created a new money pool. + Send this URL out to anyone you're inviting to + participate: + </p> + <p> + <a href="/pool?key={{key}}">http://pitch-in.appspot.com/pool?key={{key}}</a> + </p> + </div> + <div class="boxbottom"><div></div></div> + </div> </body> </html> Deleted: pitch-in/trunk/src/pitchin/pitchin/templates/index.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/index.html 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/pitchin/templates/index.html 2009-05-25 06:24:45 UTC (rev 1428) @@ -1,5 +0,0 @@ -<html> -<body> -hi -</body> -</html> Modified: pitch-in/trunk/src/pitchin/pitchin/templates/main.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/pitchin/templates/main.html 2009-05-25 06:24:45 UTC (rev 1428) @@ -1,23 +1,35 @@ <html> + <head> + <title>PitchIn!</title> + <link rel="stylesheet" type="text/css" href="static/default.css"/> + </head> <body> - <p style="color: red">{{error}}</p> - <p> - Using PitchIn, you can easily create and manage a money pool that others - can contribute to. - </p> - <p> - To create a pool, just enter a description of what it's for here, and you - will be provided a URL that you can distribute to the people you want to - participate in the pool. - </p> - <form action="/create" method="post"> - <div><input type="text" name="descrip"/></div> - <div><input type="submit" width="50" value="Create Pool"></div> - </form> - <p>Example descriptions:</p> - <ul> - <li>Birthday gift for Amy (we're aiming for $180 Rock Band set)</li> - <li>Holiday vacation trip</li> - </ul> + <div class="box"> + <div class="boxtop"><div></div></div> + <div class="header"> + <img src="static/pitchin.png"/> + </div> + <div class="body"> + <p class="line">Easily create and manage a money pool that others can contribute to.</p> + <p> + To create a pool, just enter a description of what it's for here, and you + will be provided a URL that you can distribute to the people you want to + participate in the pool. + </p> + <p class="error">{{error}}</p> + <form action="/create" method="post"> + <div> + <input class="text-input" type="text" name="descrip"/> + <input type="submit" width="50" value="Create Pool"> + </div> + </form> + <div class="example"> + <p style="font-size: larger; font-weight: bold">Example descriptions:</p> + <p>“Birthday gift for Amy (we're aiming for $180 Rock Band set)”</p> + <p>“Holiday vacation trip”</p> + </div> + </div> + <div class="boxbottom"><div></div></div> + </div> </body> </html> Modified: pitch-in/trunk/src/pitchin/pitchin/templates/pool.html =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/pitchin/templates/pool.html 2009-05-25 06:24:45 UTC (rev 1428) @@ -1,23 +1,36 @@ <html> + <head> + <title>PitchIn!</title> + <link rel="stylesheet" type="text/css" href="static/default.css"/> + </head> <body> - <p style="color: red">{{error}}</p> - <p>Description of pool: {{descrip}}</p> - {{contribs}} - <p> - To add or update your own contribution to the pool, enter - the following information: - </p> - <form action="/pool" method="post"> - <input type="hidden" name="key" value="{{key}}"/> - <div> - <label name="name">Name:</label> - <input type="text" name="name"/> + <div class="box"> + <div class="boxtop"><div></div></div> + <div class="header"> + <img src="static/pitchin.png"/> </div> - <div> - <label name="amount">Amount:</label> - $<input type="text" name="amount"/>.00 + <div class="body"> + <p style="font-size: larger"><span style="font-weight: bold">Pool:</span> {{descrip}}</p> + {{contribs}} + <p> + To add or update your own contribution to the pool, enter + the following information. + </p> + <form action="/pool" method="post"> + <p class="error">{{error}}</p> + <input type="hidden" name="key" value="{{key}}"/> + <div> + <label name="name">Name:</label> + <input type="text" name="name"/> + </div> + <div> + <label name="amount">Contribution:</label> + <input type="text" name="amount"/> + </div> + <div><input type="submit" value="Enter the pool!"/></div> + </form> </div> - <div><input type="submit" value="Enter the pool!"/></div> - </form> + <div class="boxbottom"><div></div></div> + </div> </body> </html> Modified: pitch-in/trunk/src/pitchin/pitchin/views.py =================================================================== --- pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-24 21:05:06 UTC (rev 1427) +++ pitch-in/trunk/src/pitchin/pitchin/views.py 2009-05-25 06:24:45 UTC (rev 1428) @@ -11,12 +11,14 @@ def showContribs(pool): contribs = getContribs(pool) if len(contribs) == 0: - return '<p>(no participants yet)</p>' + return '<p style="font-style: italic;">(no participants yet)</p>' else: - s = '<ul>' - for name, amount in contribs.iteritems(): - s += '<li>%s: $%d.00</li>' % (cgi.escape(name), amount) - s += '<li>TOTAL: $%d.00</li></ul>' % (sum(contribs.itervalues()),) + s = '<div class="rows">' + for i, (name, amount) in enumerate(contribs.iteritems()): + s += '<div class="row%d">%s: %d</div>' % (i % 2, cgi.escape(name), amount) + s += '<div class="aggrow">Max total: %d</div>' % (sum(contribs.itervalues()),) + s += '<div class="aggrow">If everyone paid the minimum: %d</div>' % (len(contribs) * min(contribs.itervalues()),) + s += '</div>' return s class invalid_submit(Exception): pass Added: pitch-in/trunk/src/pitchin/static/bl.png =================================================================== (Binary files differ) Property changes on: pitch-in/trunk/src/pitchin/static/bl.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pitch-in/trunk/src/pitchin/static/br.png =================================================================== (Binary files differ) Property changes on: pitch-in/trunk/src/pitchin/static/br.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pitch-in/trunk/src/pitchin/static/default.css =================================================================== --- pitch-in/trunk/src/pitchin/static/default.css (rev 0) +++ pitch-in/trunk/src/pitchin/static/default.css 2009-05-25 06:24:45 UTC (rev 1428) @@ -0,0 +1,31 @@ +body { font-family: georgia; background-color: black; } +.box { background-color: white; width: 700px; margin: 40px auto; } +.boxtop div, .boxtop, .boxbottom div, .boxbottom { + width: 100%; height: 30px; font-size: 1px; +} +.boxtop div { background: url(tl.png) no-repeat top left; } +.boxtop { background: url(tr.png) no-repeat top right; } +.header { text-align: center; width: 100%; } +.body { margin: 0 30px; text-align: center; } +.error { color: red; } +.example { background-color: #ffffcc; } +.boxbottom div { background: url(bl.png) no-repeat bottom left; } +.boxbottom { background: url(br.png) no-repeat bottom right; } +label, input { + font-family: Georgia, Times, serif; + display: block; + margin: 0 auto; + color: #0d3a57; + font-size: 30px; + padding: 4px 0; + text-align: center; + width: 75%; +} +.text-input { width: 75%; } +.quote { font-family: serif; font-size: 50pt; float: left; } +.line { width: 75%; font-size: larger; font-style: italic; margin: 0 auto; } +.rows { width: 75%; margin: 0 auto; } +.row0, .row1, .aggrow { padding-top: 3px; padding-bottom: 3px; } +.row0 { background-color: #dddddd; } +.row1 { background-color: #eeeeee; } +.aggrow { color: white; background-color: black; font-weight: bold; } Added: pitch-in/trunk/src/pitchin/static/pitchin.png =================================================================== (Binary files differ) Property changes on: pitch-in/trunk/src/pitchin/static/pitchin.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pitch-in/trunk/src/pitchin/static/tl.png =================================================================== (Binary files differ) Property changes on: pitch-in/trunk/src/pitchin/static/tl.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pitch-in/trunk/src/pitchin/static/tr.png =================================================================== (Binary files differ) Property changes on: pitch-in/trunk/src/pitchin/static/tr.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |