Removed spaces at the end of lines.

This commit is contained in:
Jeremy Fincher 2003-08-20 16:26:23 +00:00
parent 9dc1221045
commit ca646716b1
52 changed files with 5398 additions and 5379 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,275 +1,275 @@
"""Python wrapper for Amazon web APIs
This module allows you to access Amazon's web APIs,
to do things like search Amazon and get the results programmatically.
Described here:
http://www.amazon.com/webservices
You need a Amazon-provided license key to use these services.
Follow the link above to get one. These functions will look in
several places (in this order) for the license key:
- the "license_key" argument of each function
- the module-level LICENSE_KEY variable (call setLicense once to set it)
- an environment variable called AMAZON_LICENSE_KEY
- a file called ".amazonkey" in the current directory
- a file called "amazonkey.txt" in the current directory
- a file called ".amazonkey" in your home directory
- a file called "amazonkey.txt" in your home directory
- a file called ".amazonkey" in the same directory as amazon.py
- a file called "amazonkey.txt" in the same directory as amazon.py
Sample usage:
>>> import amazon
>>> amazon.setLicense('...') # must get your own key!
>>> pythonBooks = amazon.searchByKeyword('Python')
>>> pythonBooks[0].ProductName
u'Learning Python (Help for Programmers)'
>>> pythonBooks[0].URL
...
>>> pythonBooks[0].OurPrice
...
Other available functions:
- browseBestSellers
- searchByASIN
- searchByUPC
- searchByAuthor
- searchByArtist
- searchByActor
- searchByDirector
- searchByManufacturer
- searchByListMania
- searchSimilar
Other usage notes:
- Most functions can take product_line as well, see source for possible values
- All functions can take type="lite" to get less detail in results
- All functions can take page=N to get second, third, fourth page of results
- All functions can take license_key="XYZ", instead of setting it globally
- All functions can take http_proxy="http://x/y/z" which overrides your system setting
"""
__author__ = "Mark Pilgrim (f8dy@diveintomark.org)"
__version__ = "0.4"
__cvsversion__ = "$Revision$"[11:-2]
__date__ = "$Date$"[7:-2]
__copyright__ = "Copyright (c) 2002 Mark Pilgrim"
__license__ = "Python"
from xml.dom import minidom
import os, sys, getopt, cgi, urllib
try:
import timeoutsocket # http://www.timo-tasi.org/python/timeoutsocket.py
timeoutsocket.setDefaultSocketTimeout(10)
except ImportError:
pass
LICENSE_KEY = None
HTTP_PROXY = None
# don't touch the rest of these constants
class AmazonError(Exception): pass
class NoLicenseKey(Exception): pass
_amazonfile1 = ".amazonkey"
_amazonfile2 = "amazonkey.txt"
_licenseLocations = (
(lambda key: key, 'passed to the function in license_key variable'),
(lambda key: LICENSE_KEY, 'module-level LICENSE_KEY variable (call setLicense to set it)'),
(lambda key: os.environ.get('AMAZON_LICENSE_KEY', None), 'an environment variable called AMAZON_LICENSE_KEY'),
(lambda key: _contentsOf(os.getcwd(), _amazonfile1), '%s in the current directory' % _amazonfile1),
(lambda key: _contentsOf(os.getcwd(), _amazonfile2), '%s in the current directory' % _amazonfile2),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _amazonfile1), '%s in your home directory' % _amazonfile1),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _amazonfile2), '%s in your home directory' % _amazonfile2),
(lambda key: _contentsOf(_getScriptDir(), _amazonfile1), '%s in the amazon.py directory' % _amazonfile1),
(lambda key: _contentsOf(_getScriptDir(), _amazonfile2), '%s in the amazon.py directory' % _amazonfile2)
)
## administrative functions
def version():
print """PyAmazon %(__version__)s
%(__copyright__)s
released %(__date__)s
""" % globals()
## utility functions
def setLicense(license_key):
"""set license key"""
global LICENSE_KEY
LICENSE_KEY = license_key
def getLicense(license_key = None):
"""get license key
license key can come from any number of locations;
see module docs for search order"""
for get, location in _licenseLocations:
rc = get(license_key)
if rc: return rc
raise NoLicenseKey, 'get a license key at http://www.amazon.com/webservices'
def setProxy(http_proxy):
"""set HTTP proxy"""
global HTTP_PROXY
HTTP_PROXY = http_proxy
def getProxy(http_proxy = None):
"""get HTTP proxy"""
return http_proxy or HTTP_PROXY
def getProxies(http_proxy = None):
http_proxy = getProxy(http_proxy)
if http_proxy:
proxies = {"http": http_proxy}
else:
proxies = None
return proxies
def _contentsOf(dirname, filename):
filename = os.path.join(dirname, filename)
if not os.path.exists(filename): return None
fsock = open(filename)
contents = fsock.read()
fsock.close()
return contents
def _getScriptDir():
if __name__ == '__main__':
return os.path.abspath(os.path.dirname(sys.argv[0]))
else:
return os.path.abspath(os.path.dirname(sys.modules[__name__].__file__))
class Bag: pass
def unmarshal(element):
rc = Bag()
if isinstance(element, minidom.Element) and (element.tagName == 'Details'):
rc.URL = element.attributes["url"].value
childElements = [e for e in element.childNodes if isinstance(e, minidom.Element)]
if childElements:
for child in childElements:
key = child.tagName
if hasattr(rc, key):
if type(getattr(rc, key)) <> type([]):
setattr(rc, key, [getattr(rc, key)])
setattr(rc, key, getattr(rc, key) + [unmarshal(child)])
else:
setattr(rc, key, unmarshal(child))
else:
rc = "".join([e.data for e in element.childNodes if isinstance(e, minidom.Text)])
if element.tagName == 'SalesRank':
rc = int(rc.replace(',', ''))
return rc
def buildURL(search_type, keyword, product_line, type, page, license_key):
url = "http://xml.amazon.com/onca/xml?v=1.0&f=xml&t=webservices-20"
url += "&dev-t=%s" % license_key.strip()
url += "&type=%s" % type
if page:
url += "&page=%s" % page
if product_line:
url += "&mode=%s" % product_line
url += "&%s=%s" % (search_type, urllib.quote(keyword))
# print url
return url
## main functions
def search(search_type, keyword, product_line, type="heavy", page=None,
license_key = None, http_proxy = None):
"""search Amazon
You need a license key to call this function; see
http://www.amazon.com/webservices
to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
keyword - keyword to search
search_type - in (KeywordSearch, BrowseNodeSearch, AsinSearch, UpcSearch, AuthorSearch, ArtistSearch, ActorSearch, DirectorSearch, ManufacturerSearch, ListManiaSearch, SimilaritySearch)
product_line - type of product to search for. restrictions based on search_type
UpcSearch - in (music, classical)
AuthorSearch - must be "books"
ArtistSearch - in (music, classical)
ActorSearch - in (dvd, vhs, video)
DirectorSearch - in (dvd, vhs, video)
ManufacturerSearch - in (electronics, kitchen, videogames, software, photo, pc-hardware)
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: list of Bags, each Bag may contain the following attributes:
Asin - Amazon ID ("ASIN" number) of this item
Authors - list of authors
Availability - "available", etc.
BrowseList - list of related categories
Catalog - catalog type ("Book", etc)
CollectiblePrice - ?, format "$34.95"
ImageUrlLarge - URL of large image of this item
ImageUrlMedium - URL of medium image of this item
ImageUrlSmall - URL of small image of this item
Isbn - ISBN number
ListPrice - list price, format "$34.95"
Lists - list of ListMania lists that include this item
Manufacturer - manufacturer
Media - media ("Paperback", "Audio CD", etc)
NumMedia - number of different media types in which this item is available
OurPrice - Amazon price, format "$24.47"
ProductName - name of this item
ReleaseDate - release date, format "09 April, 1999"
Reviews - reviews (AvgCustomerRating, plus list of CustomerReview with Rating, Summary, Content)
SalesRank - sales rank (integer)
SimilarProducts - list of Product, which is ASIN number
ThirdPartyNewPrice - ?, format "$34.95"
URL - URL of this item
"""
license_key = getLicense(license_key)
url = buildURL(search_type, keyword, product_line, type, page, license_key)
proxies = getProxies(http_proxy)
u = urllib.FancyURLopener(proxies)
usock = u.open(url)
xmldoc = minidom.parse(usock)
usock.close()
data = unmarshal(xmldoc).ProductInfo
if hasattr(data, 'ErrorMsg'):
raise AmazonError, data.ErrorMsg
else:
return data.Details
def searchByKeyword(keyword, product_line="books", type="heavy", page=1, license_key=None, http_proxy=None):
return search("KeywordSearch", keyword, product_line, type, page, license_key, http_proxy)
def browseBestSellers(browse_node, product_line="books", type="heavy", page=1, license_key=None, http_proxy=None):
return search("BrowseNodeSearch", browse_node, product_line, type, page, license_key, http_proxy)
def searchByASIN(ASIN, type="heavy", license_key=None, http_proxy=None):
return search("AsinSearch", ASIN, None, type, None, license_key, http_proxy)
def searchByUPC(UPC, type="heavy", license_key=None, http_proxy=None):
return search("UpcSearch", UPC, None, type, None, license_key, http_proxy)
def searchByAuthor(author, type="heavy", page=1, license_key=None, http_proxy=None):
return search("AuthorSearch", author, "books", type, page, license_key, http_proxy)
def searchByArtist(artist, product_line="music", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("music", "classical"):
raise AmazonError, "product_line must be in ('music', 'classical')"
return search("ArtistSearch", artist, product_line, type, page, license_key, http_proxy)
def searchByActor(actor, product_line="dvd", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("dvd", "vhs", "video"):
raise AmazonError, "product_line must be in ('dvd', 'vhs', 'video')"
return search("ActorSearch", actor, product_line, type, page, license_key, http_proxy)
def searchByDirector(director, product_line="dvd", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("dvd", "vhs", "video"):
raise AmazonError, "product_line must be in ('dvd', 'vhs', 'video')"
return search("DirectorSearch", director, product_line, type, page, license_key, http_proxy)
def searchByManufacturer(manufacturer, product_line="pc-hardware", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("electronics", "kitchen", "videogames", "software", "photo", "pc-hardware"):
raise AmazonError, "product_line must be in ('electronics', 'kitchen', 'videogames', 'software', 'photo', 'pc-hardware')"
return search("ManufacturerSearch", manufacturer, product_line, type, page, license_key, http_proxy)
def searchByListMania(listManiaID, type="heavy", page=1, license_key=None, http_proxy=None):
return search("ListManiaSearch", listManiaID, None, type, page, license_key, http_proxy)
def searchSimilar(ASIN, type="heavy", page=1, license_key=None, http_proxy=None):
return search("SimilaritySearch", ASIN, None, type, page, license_key, http_proxy)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
"""Python wrapper for Amazon web APIs
This module allows you to access Amazon's web APIs,
to do things like search Amazon and get the results programmatically.
Described here:
http://www.amazon.com/webservices
You need a Amazon-provided license key to use these services.
Follow the link above to get one. These functions will look in
several places (in this order) for the license key:
- the "license_key" argument of each function
- the module-level LICENSE_KEY variable (call setLicense once to set it)
- an environment variable called AMAZON_LICENSE_KEY
- a file called ".amazonkey" in the current directory
- a file called "amazonkey.txt" in the current directory
- a file called ".amazonkey" in your home directory
- a file called "amazonkey.txt" in your home directory
- a file called ".amazonkey" in the same directory as amazon.py
- a file called "amazonkey.txt" in the same directory as amazon.py
Sample usage:
>>> import amazon
>>> amazon.setLicense('...') # must get your own key!
>>> pythonBooks = amazon.searchByKeyword('Python')
>>> pythonBooks[0].ProductName
u'Learning Python (Help for Programmers)'
>>> pythonBooks[0].URL
...
>>> pythonBooks[0].OurPrice
...
Other available functions:
- browseBestSellers
- searchByASIN
- searchByUPC
- searchByAuthor
- searchByArtist
- searchByActor
- searchByDirector
- searchByManufacturer
- searchByListMania
- searchSimilar
Other usage notes:
- Most functions can take product_line as well, see source for possible values
- All functions can take type="lite" to get less detail in results
- All functions can take page=N to get second, third, fourth page of results
- All functions can take license_key="XYZ", instead of setting it globally
- All functions can take http_proxy="http://x/y/z" which overrides your system setting
"""
__author__ = "Mark Pilgrim (f8dy@diveintomark.org)"
__version__ = "0.4"
__cvsversion__ = "$Revision$"[11:-2]
__date__ = "$Date$"[7:-2]
__copyright__ = "Copyright (c) 2002 Mark Pilgrim"
__license__ = "Python"
from xml.dom import minidom
import os, sys, getopt, cgi, urllib
try:
import timeoutsocket # http://www.timo-tasi.org/python/timeoutsocket.py
timeoutsocket.setDefaultSocketTimeout(10)
except ImportError:
pass
LICENSE_KEY = None
HTTP_PROXY = None
# don't touch the rest of these constants
class AmazonError(Exception): pass
class NoLicenseKey(Exception): pass
_amazonfile1 = ".amazonkey"
_amazonfile2 = "amazonkey.txt"
_licenseLocations = (
(lambda key: key, 'passed to the function in license_key variable'),
(lambda key: LICENSE_KEY, 'module-level LICENSE_KEY variable (call setLicense to set it)'),
(lambda key: os.environ.get('AMAZON_LICENSE_KEY', None), 'an environment variable called AMAZON_LICENSE_KEY'),
(lambda key: _contentsOf(os.getcwd(), _amazonfile1), '%s in the current directory' % _amazonfile1),
(lambda key: _contentsOf(os.getcwd(), _amazonfile2), '%s in the current directory' % _amazonfile2),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _amazonfile1), '%s in your home directory' % _amazonfile1),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _amazonfile2), '%s in your home directory' % _amazonfile2),
(lambda key: _contentsOf(_getScriptDir(), _amazonfile1), '%s in the amazon.py directory' % _amazonfile1),
(lambda key: _contentsOf(_getScriptDir(), _amazonfile2), '%s in the amazon.py directory' % _amazonfile2)
)
## administrative functions
def version():
print """PyAmazon %(__version__)s
%(__copyright__)s
released %(__date__)s
""" % globals()
## utility functions
def setLicense(license_key):
"""set license key"""
global LICENSE_KEY
LICENSE_KEY = license_key
def getLicense(license_key = None):
"""get license key
license key can come from any number of locations;
see module docs for search order"""
for get, location in _licenseLocations:
rc = get(license_key)
if rc: return rc
raise NoLicenseKey, 'get a license key at http://www.amazon.com/webservices'
def setProxy(http_proxy):
"""set HTTP proxy"""
global HTTP_PROXY
HTTP_PROXY = http_proxy
def getProxy(http_proxy = None):
"""get HTTP proxy"""
return http_proxy or HTTP_PROXY
def getProxies(http_proxy = None):
http_proxy = getProxy(http_proxy)
if http_proxy:
proxies = {"http": http_proxy}
else:
proxies = None
return proxies
def _contentsOf(dirname, filename):
filename = os.path.join(dirname, filename)
if not os.path.exists(filename): return None
fsock = open(filename)
contents = fsock.read()
fsock.close()
return contents
def _getScriptDir():
if __name__ == '__main__':
return os.path.abspath(os.path.dirname(sys.argv[0]))
else:
return os.path.abspath(os.path.dirname(sys.modules[__name__].__file__))
class Bag: pass
def unmarshal(element):
rc = Bag()
if isinstance(element, minidom.Element) and (element.tagName == 'Details'):
rc.URL = element.attributes["url"].value
childElements = [e for e in element.childNodes if isinstance(e, minidom.Element)]
if childElements:
for child in childElements:
key = child.tagName
if hasattr(rc, key):
if type(getattr(rc, key)) <> type([]):
setattr(rc, key, [getattr(rc, key)])
setattr(rc, key, getattr(rc, key) + [unmarshal(child)])
else:
setattr(rc, key, unmarshal(child))
else:
rc = "".join([e.data for e in element.childNodes if isinstance(e, minidom.Text)])
if element.tagName == 'SalesRank':
rc = int(rc.replace(',', ''))
return rc
def buildURL(search_type, keyword, product_line, type, page, license_key):
url = "http://xml.amazon.com/onca/xml?v=1.0&f=xml&t=webservices-20"
url += "&dev-t=%s" % license_key.strip()
url += "&type=%s" % type
if page:
url += "&page=%s" % page
if product_line:
url += "&mode=%s" % product_line
url += "&%s=%s" % (search_type, urllib.quote(keyword))
# print url
return url
## main functions
def search(search_type, keyword, product_line, type="heavy", page=None,
license_key = None, http_proxy = None):
"""search Amazon
You need a license key to call this function; see
http://www.amazon.com/webservices
to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
keyword - keyword to search
search_type - in (KeywordSearch, BrowseNodeSearch, AsinSearch, UpcSearch, AuthorSearch, ArtistSearch, ActorSearch, DirectorSearch, ManufacturerSearch, ListManiaSearch, SimilaritySearch)
product_line - type of product to search for. restrictions based on search_type
UpcSearch - in (music, classical)
AuthorSearch - must be "books"
ArtistSearch - in (music, classical)
ActorSearch - in (dvd, vhs, video)
DirectorSearch - in (dvd, vhs, video)
ManufacturerSearch - in (electronics, kitchen, videogames, software, photo, pc-hardware)
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: list of Bags, each Bag may contain the following attributes:
Asin - Amazon ID ("ASIN" number) of this item
Authors - list of authors
Availability - "available", etc.
BrowseList - list of related categories
Catalog - catalog type ("Book", etc)
CollectiblePrice - ?, format "$34.95"
ImageUrlLarge - URL of large image of this item
ImageUrlMedium - URL of medium image of this item
ImageUrlSmall - URL of small image of this item
Isbn - ISBN number
ListPrice - list price, format "$34.95"
Lists - list of ListMania lists that include this item
Manufacturer - manufacturer
Media - media ("Paperback", "Audio CD", etc)
NumMedia - number of different media types in which this item is available
OurPrice - Amazon price, format "$24.47"
ProductName - name of this item
ReleaseDate - release date, format "09 April, 1999"
Reviews - reviews (AvgCustomerRating, plus list of CustomerReview with Rating, Summary, Content)
SalesRank - sales rank (integer)
SimilarProducts - list of Product, which is ASIN number
ThirdPartyNewPrice - ?, format "$34.95"
URL - URL of this item
"""
license_key = getLicense(license_key)
url = buildURL(search_type, keyword, product_line, type, page, license_key)
proxies = getProxies(http_proxy)
u = urllib.FancyURLopener(proxies)
usock = u.open(url)
xmldoc = minidom.parse(usock)
usock.close()
data = unmarshal(xmldoc).ProductInfo
if hasattr(data, 'ErrorMsg'):
raise AmazonError, data.ErrorMsg
else:
return data.Details
def searchByKeyword(keyword, product_line="books", type="heavy", page=1, license_key=None, http_proxy=None):
return search("KeywordSearch", keyword, product_line, type, page, license_key, http_proxy)
def browseBestSellers(browse_node, product_line="books", type="heavy", page=1, license_key=None, http_proxy=None):
return search("BrowseNodeSearch", browse_node, product_line, type, page, license_key, http_proxy)
def searchByASIN(ASIN, type="heavy", license_key=None, http_proxy=None):
return search("AsinSearch", ASIN, None, type, None, license_key, http_proxy)
def searchByUPC(UPC, type="heavy", license_key=None, http_proxy=None):
return search("UpcSearch", UPC, None, type, None, license_key, http_proxy)
def searchByAuthor(author, type="heavy", page=1, license_key=None, http_proxy=None):
return search("AuthorSearch", author, "books", type, page, license_key, http_proxy)
def searchByArtist(artist, product_line="music", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("music", "classical"):
raise AmazonError, "product_line must be in ('music', 'classical')"
return search("ArtistSearch", artist, product_line, type, page, license_key, http_proxy)
def searchByActor(actor, product_line="dvd", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("dvd", "vhs", "video"):
raise AmazonError, "product_line must be in ('dvd', 'vhs', 'video')"
return search("ActorSearch", actor, product_line, type, page, license_key, http_proxy)
def searchByDirector(director, product_line="dvd", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("dvd", "vhs", "video"):
raise AmazonError, "product_line must be in ('dvd', 'vhs', 'video')"
return search("DirectorSearch", director, product_line, type, page, license_key, http_proxy)
def searchByManufacturer(manufacturer, product_line="pc-hardware", type="heavy", page=1, license_key=None, http_proxy=None):
if product_line not in ("electronics", "kitchen", "videogames", "software", "photo", "pc-hardware"):
raise AmazonError, "product_line must be in ('electronics', 'kitchen', 'videogames', 'software', 'photo', 'pc-hardware')"
return search("ManufacturerSearch", manufacturer, product_line, type, page, license_key, http_proxy)
def searchByListMania(listManiaID, type="heavy", page=1, license_key=None, http_proxy=None):
return search("ListManiaSearch", listManiaID, None, type, page, license_key, http_proxy)
def searchSimilar(ASIN, type="heavy", page=1, license_key=None, http_proxy=None):
return search("SimilaritySearch", ASIN, None, type, page, license_key, http_proxy)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -1,433 +1,433 @@
"""Python wrapper for Google web APIs
This module allows you to access Google's web APIs through SOAP,
to do things like search Google and get the results programmatically.
Described here:
http://www.google.com/apis/
You need a Google-provided license key to use these services.
Follow the link above to get one. These functions will look in
several places (in this order) for the license key:
- the "license_key" argument of each function
- the module-level LICENSE_KEY variable (call setLicense once to set it)
- an environment variable called GOOGLE_LICENSE_KEY
- a file called ".googlekey" in the current directory
- a file called "googlekey.txt" in the current directory
- a file called ".googlekey" in your home directory
- a file called "googlekey.txt" in your home directory
- a file called ".googlekey" in the same directory as google.py
- a file called "googlekey.txt" in the same directory as google.py
Sample usage:
>>> import google
>>> google.setLicense('...') # must get your own key!
>>> data = google.doGoogleSearch('python')
>>> data.meta.searchTime
0.043221000000000002
>>> data.results[0].URL
'http://www.python.org/'
>>> data.results[0].title
'<b>Python</b> Language Website'
See documentation of SearchResultsMetaData and SearchResult classes
for other available attributes.
"""
__author__ = "Mark Pilgrim (f8dy@diveintomark.org)"
__version__ = "0.5.2"
__cvsversion__ = "$Revision$"[11:-2]
__date__ = "$Date$"[7:-2]
__copyright__ = "Copyright (c) 2002 Mark Pilgrim"
__license__ = "Python"
__credits__ = """David Ascher, for the install script
Erik Max Francis, for the command line interface
Michael Twomey, for HTTP proxy support"""
import SOAP
import os, sys, getopt
LICENSE_KEY = None
HTTP_PROXY = None
# don't touch the rest of these constants
class NoLicenseKey(Exception): pass
_url = 'http://api.google.com/search/beta2'
_namespace = 'urn:GoogleSearch'
_false = SOAP.booleanType(0)
_true = SOAP.booleanType(1)
_googlefile1 = ".googlekey"
_googlefile2 = "googlekey.txt"
_licenseLocations = (
(lambda key: key, 'passed to the function in license_key variable'),
(lambda key: LICENSE_KEY, 'module-level LICENSE_KEY variable (call setLicense to set it)'),
(lambda key: os.environ.get('GOOGLE_LICENSE_KEY', None), 'an environment variable called GOOGLE_LICENSE_KEY'),
(lambda key: _contentsOf(os.getcwd(), _googlefile1), '%s in the current directory' % _googlefile1),
(lambda key: _contentsOf(os.getcwd(), _googlefile2), '%s in the current directory' % _googlefile2),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _googlefile1), '%s in your home directory' % _googlefile1),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _googlefile2), '%s in your home directory' % _googlefile2),
(lambda key: _contentsOf(_getScriptDir(), _googlefile1), '%s in the google.py directory' % _googlefile1),
(lambda key: _contentsOf(_getScriptDir(), _googlefile2), '%s in the google.py directory' % _googlefile2)
)
## administrative functions
def version():
print """PyGoogle %(__version__)s
%(__copyright__)s
released %(__date__)s
Thanks to:
%(__credits__)s""" % globals()
def usage():
program = os.path.basename(sys.argv[0])
print """Usage: %(program)s [options] [querytype] query
options:
-k, --key= <license key> Google license key (see important note below)
-1, -l, --lucky show only first hit
-m, --meta show meta information
-r, --reverse show results in reverse order
-x, --proxy= <url> use HTTP proxy
-h, --help print this help
-v, --version print version and copyright information
-t, --test run test queries
querytype:
-s, --search= <query> search (default)
-c, --cache= <url> retrieve cached page
-p, --spelling= <word> check spelling
IMPORTANT NOTE: all Google functions require a valid license key;
visit http://www.google.com/apis/ to get one. %(program)s will look in
these places (in order) and use the first license key it finds:
* the key specified on the command line""" % vars()
for get, location in _licenseLocations[2:]:
print " *", location
## utility functions
def setLicense(license_key):
"""set license key"""
global LICENSE_KEY
LICENSE_KEY = license_key
def getLicense(license_key = None):
"""get license key
license key can come from any number of locations;
see module docs for search order"""
for get, location in _licenseLocations:
rc = get(license_key)
if rc: return rc
usage()
raise NoLicenseKey, 'get a license key at http://www.google.com/apis/'
def setProxy(http_proxy):
"""set HTTP proxy"""
global HTTP_PROXY
HTTP_PROXY = http_proxy
def getProxy(http_proxy = None):
"""get HTTP proxy"""
return http_proxy or HTTP_PROXY
def _contentsOf(dirname, filename):
filename = os.path.join(dirname, filename)
if not os.path.exists(filename): return None
fsock = open(filename)
contents = fsock.read()
fsock.close()
return contents
def _getScriptDir():
if __name__ == '__main__':
return os.path.abspath(os.path.dirname(sys.argv[0]))
else:
return os.path.abspath(os.path.dirname(sys.modules[__name__].__file__))
def _marshalBoolean(value):
if value:
return _true
else:
return _false
## output formatters
def makeFormatter(outputFormat):
classname = "%sOutputFormatter" % outputFormat.capitalize()
return globals()[classname]()
def output(results, params):
formatter = makeFormatter(params.get("outputFormat", "text"))
outputmethod = getattr(formatter, params["func"])
outputmethod(results, params)
class OutputFormatter:
def boil(self, data):
if type(data) == type(u""):
return data.encode("ISO-8859-1", "replace")
else:
return data
class TextOutputFormatter(OutputFormatter):
def common(self, data, params):
if params.get("showMeta", 0):
meta = data.meta
for category in meta.directoryCategories:
print "directoryCategory: %s" % self.boil(category["fullViewableName"])
for attr in [node for node in dir(meta) if node <> "directoryCategories" and node[:2] <> '__']:
print "%s:" % attr, self.boil(getattr(meta, attr))
def doGoogleSearch(self, data, params):
results = data.results
if params.get("feelingLucky", 0):
results = results[:1]
if params.get("reverseOrder", 0):
results.reverse()
for result in results:
for attr in dir(result):
if attr == "directoryCategory":
print "directoryCategory:", self.boil(result.directoryCategory["fullViewableName"])
elif attr[:2] <> '__':
print "%s:" % attr, self.boil(getattr(result, attr))
print
self.common(data, params)
def doGetCachedPage(self, data, params):
print data
self.common(data, params)
doSpellingSuggestion = doGetCachedPage
## search results classes
class _SearchBase:
def __init__(self, params):
for k, v in params.items():
if isinstance(v, SOAP.structType):
v = v._asdict
try:
if isinstance(v[0], SOAP.structType):
v = [node._asdict for node in v]
except:
pass
self.__dict__[str(k)] = v
class SearchResultsMetaData(_SearchBase):
"""metadata of search query results
Available attributes:
documentFiltering - flag indicates whether duplicate page filtering was perfomed in this search
searchComments - human-readable informational message (example: "'the' is a very common word
and was not included in your search")
estimatedTotalResultsCount - estimated total number of results for this query
estimateIsExact - flag indicates whether estimatedTotalResultsCount is an exact value
searchQuery - search string that initiated this search
startIndex - index of first result returned (zero-based)
endIndex - index of last result returned (zero-based)
searchTips - human-readable informational message on how to use Google bette
directoryCategories - list of dictionaries like this:
{'fullViewableName': Open Directory category,
'specialEncoding': encoding scheme of this directory category}
searchTime - total search time, in seconds
"""
pass
class SearchResult(_SearchBase):
"""search result
Available attributes:
URL - URL
title - title (HTML)
snippet - snippet showing query context (HTML)
cachedSize - size of cached version of this result, (KB)
relatedInformationPresent - flag indicates that the "related:" keyword is supported for this URL
hostName: When filtering occurs, a maximum of two results from any given host is returned.
When this occurs, the second resultElement that comes from that host contains
the host name in this parameter.
directoryCategory: dictionary like this:
{'fullViewableName': Open Directory category,
'specialEncoding': encoding scheme of this directory category}
directoryTitle: Open Directory title of this result (or blank)
summary - Open Directory summary for this result (or blank)
"""
pass
class SearchReturnValue:
"""complete search results for a single query
Available attributes:
meta - SearchResultsMetaData
results - list of SearchResult
"""
def __init__(self, metadata, results):
self.meta = metadata
self.results = results
## main functions
def doGoogleSearch(q, start=0, maxResults=10, filter=1, restrict='',
safeSearch=0, language='', inputencoding='', outputencoding='',
license_key = None, http_proxy = None):
"""search Google
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
q - search string. Anything you could type at google.com, you can pass here.
See http://www.google.com/help/features.html for examples of advanced features.
start (optional) - zero-based index of first desired result (for paging through
multiple pages of results)
maxResults (optional) - maximum number of results, currently capped at 10
filter (optional) - set to 1 to filter out similar results, set to 0 to see everything
restrict (optional) - restrict results by country or topic. Examples:
Ukraine - search only sites located in Ukraine
linux - search Linux sites only
mac - search Mac sites only
bsd - search FreeBSD sites only
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for more advanced examples and a full list of country codes and topics.
safeSearch (optional) - set to 1 to filter results with SafeSearch (no adult material)
language (optional) - restricts search to documents in one or more languages. Example:
lang_en - only return pages in English
lang_fr - only return pages in French
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for more advanced examples and a full list of language codes.
inputencoding (optional) - sets the character encoding of q parameter
outputencoding (optional) - sets the character encoding of the returned results
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for a full list of encodings.
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: SearchReturnValue
.meta - SearchMetaData
.results - list of SearchResult
See documentation of these individual classes for list of available attributes
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
filter = _marshalBoolean(filter)
safeSearch = _marshalBoolean(safeSearch)
data = remoteserver.doGoogleSearch(license_key, q, start, maxResults, filter, restrict,
safeSearch, language, inputencoding, outputencoding)
metadata = data._asdict
del metadata["resultElements"]
metadata = SearchResultsMetaData(metadata)
results = [SearchResult(node._asdict) for node in data.resultElements]
return SearchReturnValue(metadata, results)
def doGetCachedPage(url, license_key = None, http_proxy = None):
"""get page from Google cache
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
url - address of page to get
license_key (optional) - Google license key
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: string, text of cached page
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
return remoteserver.doGetCachedPage(license_key, url)
def doSpellingSuggestion(phrase, license_key = None, http_proxy = None):
"""get spelling suggestions from Google
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
phrase - word or phrase to spell-check
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: text of suggested replacement, or None
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
return remoteserver.doSpellingSuggestion(license_key, phrase)
## functional test suite (see googletest.py for unit test suite)
def test():
try:
getLicense(None)
except NoLicenseKey:
return
print "Searching for Python at google.com..."
data = doGoogleSearch("Python")
output(data, {"func": "doGoogleSearch"})
print "\nSearching for 5 _French_ pages about Python, encoded in ISO-8859-1..."
data = doGoogleSearch("Python", language='lang_fr', outputencoding='ISO-8859-1', maxResults=5)
output(data, {"func": "doGoogleSearch"})
phrase = "Pyhton programming languager"
print "\nTesting spelling suggetions for '%s'..." % phrase
data = doSpellingSuggestion(phrase)
output(data, {"func": "doSpellingSuggestion"})
## main driver for command-line use
def main(argv):
if not argv:
usage()
return
q = None
func = None
http_proxy = None
license_key = None
feelingLucky = 0
showMeta = 0
reverseOrder = 0
runTest = 0
outputFormat = "text"
try:
opts, args = getopt.getopt(argv, "s:c:p:k:lmrx:hvt1",
["search=", "cache=", "spelling=", "key=", "lucky", "meta", "reverse", "proxy=", "help", "version", "test"])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-s", "--search"):
q = arg
func = "doGoogleSearch"
elif opt in ("-c", "--cache"):
q = arg
func = "doGetCachedPage"
elif opt in ("-p", "--spelling"):
q = arg
func = "doSpellingSuggestion"
elif opt in ("-k", "--key"):
license_key = arg
elif opt in ("-l", "-1", "--lucky"):
feelingLucky = 1
elif opt in ("-m", "--meta"):
showMeta = 1
elif opt in ("-r", "--reverse"):
reverseOrder = 1
elif opt in ("-x", "--proxy"):
http_proxy = arg
elif opt in ("-h", "--help"):
usage()
elif opt in ("-v", "--version"):
version()
elif opt in ("-t", "--test"):
runTest = 1
if runTest:
setLicense(license_key)
setProxy(http_proxy)
test()
if args and not q:
q = args[0]
func = "doGoogleSearch"
if func:
results = globals()[func](q, http_proxy=http_proxy, license_key=license_key)
output(results, locals())
if __name__ == '__main__':
main(sys.argv[1:])
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
"""Python wrapper for Google web APIs
This module allows you to access Google's web APIs through SOAP,
to do things like search Google and get the results programmatically.
Described here:
http://www.google.com/apis/
You need a Google-provided license key to use these services.
Follow the link above to get one. These functions will look in
several places (in this order) for the license key:
- the "license_key" argument of each function
- the module-level LICENSE_KEY variable (call setLicense once to set it)
- an environment variable called GOOGLE_LICENSE_KEY
- a file called ".googlekey" in the current directory
- a file called "googlekey.txt" in the current directory
- a file called ".googlekey" in your home directory
- a file called "googlekey.txt" in your home directory
- a file called ".googlekey" in the same directory as google.py
- a file called "googlekey.txt" in the same directory as google.py
Sample usage:
>>> import google
>>> google.setLicense('...') # must get your own key!
>>> data = google.doGoogleSearch('python')
>>> data.meta.searchTime
0.043221000000000002
>>> data.results[0].URL
'http://www.python.org/'
>>> data.results[0].title
'<b>Python</b> Language Website'
See documentation of SearchResultsMetaData and SearchResult classes
for other available attributes.
"""
__author__ = "Mark Pilgrim (f8dy@diveintomark.org)"
__version__ = "0.5.2"
__cvsversion__ = "$Revision$"[11:-2]
__date__ = "$Date$"[7:-2]
__copyright__ = "Copyright (c) 2002 Mark Pilgrim"
__license__ = "Python"
__credits__ = """David Ascher, for the install script
Erik Max Francis, for the command line interface
Michael Twomey, for HTTP proxy support"""
import SOAP
import os, sys, getopt
LICENSE_KEY = None
HTTP_PROXY = None
# don't touch the rest of these constants
class NoLicenseKey(Exception): pass
_url = 'http://api.google.com/search/beta2'
_namespace = 'urn:GoogleSearch'
_false = SOAP.booleanType(0)
_true = SOAP.booleanType(1)
_googlefile1 = ".googlekey"
_googlefile2 = "googlekey.txt"
_licenseLocations = (
(lambda key: key, 'passed to the function in license_key variable'),
(lambda key: LICENSE_KEY, 'module-level LICENSE_KEY variable (call setLicense to set it)'),
(lambda key: os.environ.get('GOOGLE_LICENSE_KEY', None), 'an environment variable called GOOGLE_LICENSE_KEY'),
(lambda key: _contentsOf(os.getcwd(), _googlefile1), '%s in the current directory' % _googlefile1),
(lambda key: _contentsOf(os.getcwd(), _googlefile2), '%s in the current directory' % _googlefile2),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _googlefile1), '%s in your home directory' % _googlefile1),
(lambda key: _contentsOf(os.environ.get('HOME', ''), _googlefile2), '%s in your home directory' % _googlefile2),
(lambda key: _contentsOf(_getScriptDir(), _googlefile1), '%s in the google.py directory' % _googlefile1),
(lambda key: _contentsOf(_getScriptDir(), _googlefile2), '%s in the google.py directory' % _googlefile2)
)
## administrative functions
def version():
print """PyGoogle %(__version__)s
%(__copyright__)s
released %(__date__)s
Thanks to:
%(__credits__)s""" % globals()
def usage():
program = os.path.basename(sys.argv[0])
print """Usage: %(program)s [options] [querytype] query
options:
-k, --key= <license key> Google license key (see important note below)
-1, -l, --lucky show only first hit
-m, --meta show meta information
-r, --reverse show results in reverse order
-x, --proxy= <url> use HTTP proxy
-h, --help print this help
-v, --version print version and copyright information
-t, --test run test queries
querytype:
-s, --search= <query> search (default)
-c, --cache= <url> retrieve cached page
-p, --spelling= <word> check spelling
IMPORTANT NOTE: all Google functions require a valid license key;
visit http://www.google.com/apis/ to get one. %(program)s will look in
these places (in order) and use the first license key it finds:
* the key specified on the command line""" % vars()
for get, location in _licenseLocations[2:]:
print " *", location
## utility functions
def setLicense(license_key):
"""set license key"""
global LICENSE_KEY
LICENSE_KEY = license_key
def getLicense(license_key = None):
"""get license key
license key can come from any number of locations;
see module docs for search order"""
for get, location in _licenseLocations:
rc = get(license_key)
if rc: return rc
usage()
raise NoLicenseKey, 'get a license key at http://www.google.com/apis/'
def setProxy(http_proxy):
"""set HTTP proxy"""
global HTTP_PROXY
HTTP_PROXY = http_proxy
def getProxy(http_proxy = None):
"""get HTTP proxy"""
return http_proxy or HTTP_PROXY
def _contentsOf(dirname, filename):
filename = os.path.join(dirname, filename)
if not os.path.exists(filename): return None
fsock = open(filename)
contents = fsock.read()
fsock.close()
return contents
def _getScriptDir():
if __name__ == '__main__':
return os.path.abspath(os.path.dirname(sys.argv[0]))
else:
return os.path.abspath(os.path.dirname(sys.modules[__name__].__file__))
def _marshalBoolean(value):
if value:
return _true
else:
return _false
## output formatters
def makeFormatter(outputFormat):
classname = "%sOutputFormatter" % outputFormat.capitalize()
return globals()[classname]()
def output(results, params):
formatter = makeFormatter(params.get("outputFormat", "text"))
outputmethod = getattr(formatter, params["func"])
outputmethod(results, params)
class OutputFormatter:
def boil(self, data):
if type(data) == type(u""):
return data.encode("ISO-8859-1", "replace")
else:
return data
class TextOutputFormatter(OutputFormatter):
def common(self, data, params):
if params.get("showMeta", 0):
meta = data.meta
for category in meta.directoryCategories:
print "directoryCategory: %s" % self.boil(category["fullViewableName"])
for attr in [node for node in dir(meta) if node <> "directoryCategories" and node[:2] <> '__']:
print "%s:" % attr, self.boil(getattr(meta, attr))
def doGoogleSearch(self, data, params):
results = data.results
if params.get("feelingLucky", 0):
results = results[:1]
if params.get("reverseOrder", 0):
results.reverse()
for result in results:
for attr in dir(result):
if attr == "directoryCategory":
print "directoryCategory:", self.boil(result.directoryCategory["fullViewableName"])
elif attr[:2] <> '__':
print "%s:" % attr, self.boil(getattr(result, attr))
print
self.common(data, params)
def doGetCachedPage(self, data, params):
print data
self.common(data, params)
doSpellingSuggestion = doGetCachedPage
## search results classes
class _SearchBase:
def __init__(self, params):
for k, v in params.items():
if isinstance(v, SOAP.structType):
v = v._asdict
try:
if isinstance(v[0], SOAP.structType):
v = [node._asdict for node in v]
except:
pass
self.__dict__[str(k)] = v
class SearchResultsMetaData(_SearchBase):
"""metadata of search query results
Available attributes:
documentFiltering - flag indicates whether duplicate page filtering was perfomed in this search
searchComments - human-readable informational message (example: "'the' is a very common word
and was not included in your search")
estimatedTotalResultsCount - estimated total number of results for this query
estimateIsExact - flag indicates whether estimatedTotalResultsCount is an exact value
searchQuery - search string that initiated this search
startIndex - index of first result returned (zero-based)
endIndex - index of last result returned (zero-based)
searchTips - human-readable informational message on how to use Google bette
directoryCategories - list of dictionaries like this:
{'fullViewableName': Open Directory category,
'specialEncoding': encoding scheme of this directory category}
searchTime - total search time, in seconds
"""
pass
class SearchResult(_SearchBase):
"""search result
Available attributes:
URL - URL
title - title (HTML)
snippet - snippet showing query context (HTML)
cachedSize - size of cached version of this result, (KB)
relatedInformationPresent - flag indicates that the "related:" keyword is supported for this URL
hostName: When filtering occurs, a maximum of two results from any given host is returned.
When this occurs, the second resultElement that comes from that host contains
the host name in this parameter.
directoryCategory: dictionary like this:
{'fullViewableName': Open Directory category,
'specialEncoding': encoding scheme of this directory category}
directoryTitle: Open Directory title of this result (or blank)
summary - Open Directory summary for this result (or blank)
"""
pass
class SearchReturnValue:
"""complete search results for a single query
Available attributes:
meta - SearchResultsMetaData
results - list of SearchResult
"""
def __init__(self, metadata, results):
self.meta = metadata
self.results = results
## main functions
def doGoogleSearch(q, start=0, maxResults=10, filter=1, restrict='',
safeSearch=0, language='', inputencoding='', outputencoding='',
license_key = None, http_proxy = None):
"""search Google
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
q - search string. Anything you could type at google.com, you can pass here.
See http://www.google.com/help/features.html for examples of advanced features.
start (optional) - zero-based index of first desired result (for paging through
multiple pages of results)
maxResults (optional) - maximum number of results, currently capped at 10
filter (optional) - set to 1 to filter out similar results, set to 0 to see everything
restrict (optional) - restrict results by country or topic. Examples:
Ukraine - search only sites located in Ukraine
linux - search Linux sites only
mac - search Mac sites only
bsd - search FreeBSD sites only
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for more advanced examples and a full list of country codes and topics.
safeSearch (optional) - set to 1 to filter results with SafeSearch (no adult material)
language (optional) - restricts search to documents in one or more languages. Example:
lang_en - only return pages in English
lang_fr - only return pages in French
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for more advanced examples and a full list of language codes.
inputencoding (optional) - sets the character encoding of q parameter
outputencoding (optional) - sets the character encoding of the returned results
See the APIs_reference.html file in the SDK (http://www.google.com/apis/download.html)
for a full list of encodings.
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: SearchReturnValue
.meta - SearchMetaData
.results - list of SearchResult
See documentation of these individual classes for list of available attributes
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
filter = _marshalBoolean(filter)
safeSearch = _marshalBoolean(safeSearch)
data = remoteserver.doGoogleSearch(license_key, q, start, maxResults, filter, restrict,
safeSearch, language, inputencoding, outputencoding)
metadata = data._asdict
del metadata["resultElements"]
metadata = SearchResultsMetaData(metadata)
results = [SearchResult(node._asdict) for node in data.resultElements]
return SearchReturnValue(metadata, results)
def doGetCachedPage(url, license_key = None, http_proxy = None):
"""get page from Google cache
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
url - address of page to get
license_key (optional) - Google license key
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: string, text of cached page
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
return remoteserver.doGetCachedPage(license_key, url)
def doSpellingSuggestion(phrase, license_key = None, http_proxy = None):
"""get spelling suggestions from Google
You need a license key to call this function; see
http://www.google.com/apis/ to get one. Then you can either pass it to
this function every time, or set it globally; see the module docs for details.
Parameters:
phrase - word or phrase to spell-check
http_proxy (optional) - address of HTTP proxy to use for sending and receiving SOAP messages
Returns: text of suggested replacement, or None
"""
http_proxy = getProxy(http_proxy)
remoteserver = SOAP.SOAPProxy(_url, namespace=_namespace, http_proxy=http_proxy)
license_key = getLicense(license_key)
return remoteserver.doSpellingSuggestion(license_key, phrase)
## functional test suite (see googletest.py for unit test suite)
def test():
try:
getLicense(None)
except NoLicenseKey:
return
print "Searching for Python at google.com..."
data = doGoogleSearch("Python")
output(data, {"func": "doGoogleSearch"})
print "\nSearching for 5 _French_ pages about Python, encoded in ISO-8859-1..."
data = doGoogleSearch("Python", language='lang_fr', outputencoding='ISO-8859-1', maxResults=5)
output(data, {"func": "doGoogleSearch"})
phrase = "Pyhton programming languager"
print "\nTesting spelling suggetions for '%s'..." % phrase
data = doSpellingSuggestion(phrase)
output(data, {"func": "doSpellingSuggestion"})
## main driver for command-line use
def main(argv):
if not argv:
usage()
return
q = None
func = None
http_proxy = None
license_key = None
feelingLucky = 0
showMeta = 0
reverseOrder = 0
runTest = 0
outputFormat = "text"
try:
opts, args = getopt.getopt(argv, "s:c:p:k:lmrx:hvt1",
["search=", "cache=", "spelling=", "key=", "lucky", "meta", "reverse", "proxy=", "help", "version", "test"])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-s", "--search"):
q = arg
func = "doGoogleSearch"
elif opt in ("-c", "--cache"):
q = arg
func = "doGetCachedPage"
elif opt in ("-p", "--spelling"):
q = arg
func = "doSpellingSuggestion"
elif opt in ("-k", "--key"):
license_key = arg
elif opt in ("-l", "-1", "--lucky"):
feelingLucky = 1
elif opt in ("-m", "--meta"):
showMeta = 1
elif opt in ("-r", "--reverse"):
reverseOrder = 1
elif opt in ("-x", "--proxy"):
http_proxy = arg
elif opt in ("-h", "--help"):
usage()
elif opt in ("-v", "--version"):
version()
elif opt in ("-t", "--test"):
runTest = 1
if runTest:
setLicense(license_key)
setProxy(http_proxy)
test()
if args and not q:
q = args[0]
func = "doGoogleSearch"
if func:
results = globals()[func](q, http_proxy=http_proxy, license_key=license_key)
output(results, locals())
if __name__ == '__main__':
main(sys.argv[1:])
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -387,7 +387,7 @@ class Message:
def __contains__(self, name):
return name.lower() in self.dict
def __getitem__(self, name):
"""Get a specific header, as from a dictionary."""
return self.dict[name.lower()]

File diff suppressed because it is too large Load Diff

View File

@ -263,7 +263,7 @@ class TestCase:
def _fail(self, msg):
"""Underlying implementation of failure."""
raise self.failureException, msg
def fail(self, msg=None):
"""Fail immediately, with the given message."""
global asserts

View File

@ -66,7 +66,7 @@ def findBiggestDollar(alias):
return int(dollars[-1])
else:
return None
def makeNewAlias(name, alias):
if findAliasCommand(name, alias):
raise RecursiveAlias
@ -105,7 +105,7 @@ class Alias(callbacks.Privmsg):
def __init__(self):
callbacks.Privmsg.__init__(self)
self.frozen = sets.Set()
def freeze(self, irc, msg, args):
"""<alias>
@ -133,7 +133,7 @@ class Alias(callbacks.Privmsg):
else:
irc.error(msg, 'There is no such alias.')
unfreeze = privmsgs.checkCapability(unfreeze, 'admin')
def alias(self, irc, msg, args):
"""<name> <alias commands>
@ -164,7 +164,7 @@ class Alias(callbacks.Privmsg):
print debug.exnToString(e)
except:
print 'exception raised'
def unalias(self, irc, msg, args):
"""<name>
@ -181,8 +181,8 @@ class Alias(callbacks.Privmsg):
irc.error(msg, 'That alias is frozen.')
else:
irc.error(msg, 'There is no such alias.')
Class = Alias

View File

@ -111,7 +111,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
)""")
db.commit()
return db
def doPrivmsg(self, irc, msg):
callbacks.PrivmsgCommandAndRegexp.doPrivmsg(self, irc, msg)
if ircutils.isChannel(msg.args[0]):
@ -174,7 +174,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
except KeyError:
pass
db.commit()
def doPart(self, irc, msg):
channel = msg.args[0]
db = self.getDb(channel)

View File

@ -30,7 +30,7 @@
###
"""
Handles standard CTCP responses to PING, TIME, SOURCE, VERSION, USERINFO,
Handles standard CTCP responses to PING, TIME, SOURCE, VERSION, USERINFO,
and FINGER.
"""

View File

@ -30,7 +30,7 @@
###
"""
Handles "factoids," little tidbits of information held in a database and
Handles "factoids," little tidbits of information held in a database and
available on demand via several commands.
Commands include:
@ -59,7 +59,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
def __init__(self):
ChannelDBHandler.__init__(self)
callbacks.Privmsg.__init__(self)
def makeDb(self, filename):
if os.path.exists(filename):
return sqlite.connect(filename)
@ -120,7 +120,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
irc.reply(msg, conf.replySuccess)
else:
irc.error(msg, 'That factoid is locked.')
def lookup(self, irc, msg, args):
"[<channel>] (If not sent in the channel itself) <key> [<number>]"
channel = privmsgs.getChannel(msg, args)
@ -141,7 +141,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
else:
factoid = results[number][0]
irc.reply(msg, '%s/%s: %s' % (key, number, factoid))
def lock(self, irc, msg, args):
"[<channel>] (If not sent in the channel itself) <key>"
channel = privmsgs.getChannel(msg, args)
@ -155,7 +155,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
irc.reply(msg, conf.replySuccess)
else:
irc.error(msg, conf.replyNoCapability % capability)
def unlock(self, irc, msg, args):
"[<channel>] (If not sent in the channel itself) <key>"
channel = privmsgs.getChannel(msg, args)
@ -183,7 +183,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
irc.reply(msg, conf.replySuccess)
else:
irc.error(msg, conf.replyNoCapability % capability)
def randomfactoid(self, irc, msg, args):
"[<channel>] (If not sent in the channel itself)"
channel = privmsgs.getChannel(msg, args)
@ -226,7 +226,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
s = 'Key %r is %s and has %s factoids associated with it: %s' % \
(key, locked and 'locked' or 'not locked', counter, '; '.join(L))
irc.reply(msg, s)
Class = Factoids

View File

@ -204,8 +204,8 @@ class FreeBSD(callbacks.Privmsg):
'Please narrow your search.' % cursor.rowcount)
else:
irc.reply(msg, ', '.join(names))
def numports(self, irc, msg, args):
"""takes no arguments
@ -249,10 +249,10 @@ class FreeBSD(callbacks.Privmsg):
categories = map(lambda t: t[0], cursor.fetchall())
irc.reply(msg, '%s; Categories: %s; Maintainer: %s; Website: %s' %
(info, ', '.join(categories), maintainer, website))
Class = FreeBSD
if __name__ == '__main__':
makeDb(dbFile, getIndex(), replace=True)

View File

@ -52,7 +52,7 @@ class Friendly(callbacks.PrivmsgRegexp):
if match.group(1) == irc.nick:
irc.queueMsg(ircmsgs.privmsg(msg.args[0], '%s!' % msg.nick))
Class = Friendly
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -122,7 +122,7 @@ class FunCommands(callbacks.Privmsg):
irc.reply(msg, chr(i))
except ValueError:
irc.error(msg, 'That number doesn\'t map to an 8-bit character.')
def base(self, irc, msg, args):
"""<base> <number>
@ -154,7 +154,7 @@ class FunCommands(callbacks.Privmsg):
LL.reverse()
L.extend(LL)
irc.reply(msg, ''.join(L))
def encode(self, irc, msg, args):
"""<encoding> <text>
@ -173,7 +173,7 @@ class FunCommands(callbacks.Privmsg):
"""
encoding, text = privmsgs.getArgs(args, needed=2)
irc.reply(msg, text.decode(encoding).encode('utf-8'))
def hexlify(self, irc, msg, args):
"""<text>
@ -323,7 +323,7 @@ class FunCommands(callbacks.Privmsg):
text = text.replace('x', 'kth')
text = text.replace('X', 'KTH')
irc.reply(msg, text)
_leettrans = string.maketrans('oOaAeElBTiIts', '004433187!1+5')
_leetres = ((re.compile(r'\b(?:(?:[yY][o0O][oO0uU])|u)\b'), 'j00'),
(re.compile(r'fear'), 'ph33r'),
@ -405,7 +405,7 @@ class FunCommands(callbacks.Privmsg):
return '%s*i' % imag
else:
return '%s+%si' % (real, imag)
def calc(self, irc, msg, args):
"""<math expression>
@ -540,7 +540,7 @@ class FunCommands(callbacks.Privmsg):
def lastfrom(self, irc, msg, args):
"""[<channel>] <nick>
Returns the last message in <channel> from <nick>. <channel> is only
Returns the last message in <channel> from <nick>. <channel> is only
necessary if the message isn't sent in the channel itself.
"""
channel = privmsgs.getChannel(msg, args)
@ -616,7 +616,7 @@ class FunCommands(callbacks.Privmsg):
irc.error(msg, 'That function has no documentation.')
return
irc.reply(msg, s)
Class = FunCommands

View File

@ -104,7 +104,7 @@ def addWord(db, word, commit=False):
WHERE word=%s))""", word, sorted)
if commit:
db.commit()
class FunDB(callbacks.Privmsg):
"""
@ -119,7 +119,7 @@ class FunDB(callbacks.Privmsg):
def die(self):
self.db.commit()
self.db.close()
'''
def praise(self, irc, msg, args):
"""<something>
@ -182,7 +182,7 @@ class FunDB(callbacks.Privmsg):
irc.error(msg, 'There is no such insult.')
else:
irc.reply(msg, cursor.fetchone()[0])
def addinsult(self, irc, msg, args):
"""<insult>
@ -267,7 +267,7 @@ class FunDB(callbacks.Privmsg):
irc.error(msg, 'There is no such excuse.')
else:
irc.reply(msg, cursor.fetchone()[0])
def addexcuse(self, irc, msg, args):
"""<excuse>
@ -294,7 +294,7 @@ class FunDB(callbacks.Privmsg):
cursor.execute("""DELETE FROM excuses WHERE id=%s""", id)
self.db.commit()
irc.reply(msg, conf.replySuccess)
def numexcuses(self, irc, msg, args):
"""takes no arguments
@ -343,7 +343,7 @@ class FunDB(callbacks.Privmsg):
irc.error(msg, 'There is no such lart.')
else:
irc.reply(msg, cursor.fetchone()[0])
def addlart(self, irc, msg, args):
"""<lart>
@ -377,7 +377,7 @@ class FunDB(callbacks.Privmsg):
def numlarts(self, irc, msg, args):
"""takes no arguments
Returns the number of larts currently in the database.
"""
cursor = self.db.cursor()
@ -443,7 +443,7 @@ class FunDB(callbacks.Privmsg):
else:
(city, state) = cursor.fetchone()
irc.reply(msg, '%s, %s' % (city, state))
def zipcodefor(self, irc, msg, args):
"""<city> <state>
@ -474,7 +474,7 @@ class FunDB(callbacks.Privmsg):
random.shuffle(zipcodes)
irc.reply(msg, '(%s shown of %s): %s' % \
(len(zipcodes), cursor.rowcount, ', '.join(zipcodes)))
Class = FunDB
@ -520,5 +520,5 @@ if __name__ == '__main__':
zipcode, city, state)
db.commit()
db.close()
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -116,8 +116,8 @@ class Gameknot(callbacks.PrivmsgCommandAndRegexp):
raise callbacks.Error, 'The format of the page was odd.'
except urllib2.URLError:
raise callbacks.Error, 'Couldn\'t connect to gameknot.com'
def gkstats(self, irc, msg, args):
"""<name>

View File

@ -212,7 +212,7 @@ class Http(callbacks.Privmsg):
irc.error(msg, 'Couldn\'t open search page.')
'''
_tempregex = re.compile('CLASS=obsTempTextA>(\d+)&deg;F</b></td>',\
re.IGNORECASE)
_cityregex = re.compile(r'Local Forecast for (.*), (.*?) ')
@ -263,7 +263,7 @@ class Http(callbacks.Privmsg):
quote = utils.htmlToText(m.group(1))
quote = ' // '.join(quote.splitlines())
irc.reply(msg, quote)
_acronymre = re.compile(r'<td[^w]+width="70[^>]+>(?:<b>)?([^<]+)(?:</b>)?')
def acronym(self, irc, msg, args):
"""<acronym>
@ -321,7 +321,7 @@ class Http(callbacks.Privmsg):
_debBranches = ('stable', 'testing', 'unstable', 'experimental')
def debversion(self, irc, msg, args):
"""<package name> [stable|testing|unstable|experimental]
Returns the current version(s) of a Debian package in the given branch
(if any, otherwise all available ones are displayed).
"""
@ -363,7 +363,7 @@ class Http(callbacks.Privmsg):
(numberOfPackages, len(responses), ', '.join(responses))
irc.reply(msg, s)
Class = Http

View File

@ -131,7 +131,7 @@ class Infobot(callbacks.PrivmsgRegexp):
irc.queueMsg(ircmsgs.privmsg(nick, s))
except KeyError:
irc.reply(msg, 'I don\'t know anything about %s' % key)
def factoid(self, irc, msg, match):
r"^(no[ :,-]+)?(.+?)\s+(was|is|am|were|are)\s+(also\s+)?(.+?)(?!\?+)$"
(correction, key, isAre, addition, value) = match.groups()
@ -151,7 +151,7 @@ class Infobot(callbacks.PrivmsgRegexp):
else:
self.insertFactoid(key, isAre, value)
irc.reply(msg, self.getRandomSaying('confirms'))
def unknown(self, irc, msg, match):
r"^(.+?)\?[?.! ]*$"
key = match.group(1)
@ -169,12 +169,12 @@ class Infobot(callbacks.PrivmsgRegexp):
numAre = cursor.fetchone()[0]
s = 'I have %s is factoids and %s are factoids' % (numIs, numAre)
irc.reply(msg, s)
Class = Infobot
if __name__ == '__main__':
import sys
if len(sys.argv) < 2 and sys.argv[1] not in ('is', 'are'):
@ -202,5 +202,5 @@ if __name__ == '__main__':
print 'Invalid line (%s): %r' %(debug.exnToString(e),line)
db.commit()
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -53,7 +53,7 @@ class KillBold(callbacks.Privmsg):
return ircmsgs.privmsg(msg.args[0],msg.args[1].replace('\x02', ''))
else:
return msg
Class = KillBold
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -39,12 +39,14 @@ Commands include:
from baseplugin import *
import re
import time
import conf
import ircdb
import ircmsgs
import privmsgs
import ircutils
import schedule
import callbacks
def configure(onStart, afterConnect, advanced):
@ -55,20 +57,21 @@ def configure(onStart, afterConnect, advanced):
onStart.append('startnickserv %s %s' % (nick, password))
class NickServ(privmsgs.CapabilityCheckingPrivmsg):
capability = 'owner'
capability = 'admin'
def __init__(self):
callbacks.Privmsg.__init__(self)
self.nickserv = ''
def startnickserv(self, irc, msg, args):
"<bot's nick> <password> <NickServ's nick (defaults to NickServ)>"
"<bot's nick> <password> <NickServ's nick (defaults to NickServ)> " \
"<ChanServ's nick (defaults to ChanServ)"
if ircutils.isChannel(msg.args[0]):
irc.error(msg, conf.replyRequiresPrivacy)
return
(self.nick, self.password, nickserv) = privmsgs.getArgs(args,
needed=2,
optional=1)
(self.nick, self.password, nickserv, chanserv) = \
privmsgs.getArgs(args, needed=2, optional=2)
self.nickserv = nickserv or 'NickServ'
self.chanserv = chanserv or 'ChanServ'
self.sentGhost = False
self._ghosted = re.compile('%s.*killed' % self.nick)
irc.reply(msg, conf.replySuccess)
@ -94,6 +97,19 @@ class NickServ(privmsgs.CapabilityCheckingPrivmsg):
ghost = 'GHOST %s %s' % (self.nick, self.password)
irc.queueMsg(ircmsgs.privmsg(self.nickserv, ghost))
self.sentGhost = True
def flipSentGhost():
self.sentGhost = False
schedule.addEvent(flipSentGhost, time.time() + 300)
def getops(self, irc, msg, args):
"""[<channel>]
Attempts to get ops from ChanServ in <channel>. If no channel is
given, the current channel is assumed.
"""
channel = privmsgs.getChannel(msg, args)
irc.sendMsg(ircmsgs.privmsg(self.chanserv, 'op %s' % channel))
Class = NickServ

View File

@ -79,20 +79,20 @@ class Notes(callbacks.Privmsg):
note TEXT
)""")
self.db.commit()
def _addUser(self, username):
"Not callable from channel, used to add users to database."
cursor = self.db.cursor()
cursor.execute('INSERT INTO users VALUES (NULL, %s)', username)
self.db.commit()
def getUserId(self, username):
"Returns the user id matching the given username from the users table."
cursor = self.db.cursor()
cursor.execute('SELECT id FROM users where name=%s', username)
if cursor.rowcount != 0:
return cursor.fetchone()[0]
else:
else:
raise KeyError, username
def getUserName(self, userid):
@ -116,7 +116,7 @@ class Notes(callbacks.Privmsg):
"Called when module is unloaded/reloaded."
self.db.commit()
self.db.close()
def doJoin(self, irc, msg):
try:
name = ircdb.users.getUserName(msg.prefix)
@ -151,7 +151,7 @@ class Notes(callbacks.Privmsg):
def sendnote(self, irc, msg, args):
"""<recipient> <text>
Sends a new note to the user specified.
"""
(name, note) = privmsgs.getArgs(args, needed=2)
@ -165,13 +165,13 @@ class Notes(callbacks.Privmsg):
self._addUser(recipient)
senderId = self.getUserId(sender)
recipId = self.getUserId(recipient)
if ircutils.isChannel(msg.args[0]):
if ircutils.isChannel(msg.args[0]):
public = 1
else:
public = 0
else:
public = 0
cursor = self.db.cursor()
cursor.execute("""INSERT INTO notes VALUES
(NULL, %s, %s, %s, 0, 0, %s, %s)""",
cursor.execute("""INSERT INTO notes VALUES
(NULL, %s, %s, %s, 0, 0, %s, %s)""",
senderId, recipId, int(time.time()),
public, note)
self.db.commit()
@ -179,7 +179,7 @@ class Notes(callbacks.Privmsg):
def note(self, irc, msg, args):
"""<note id>
Retrieves a single note by unique note id.
"""
noteid = privmsgs.getArgs(args)
@ -191,7 +191,7 @@ class Notes(callbacks.Privmsg):
return
cursor = self.db.cursor()
cursor.execute("""SELECT notes.note, notes.to_id, notes.from_id,
notes.added_at, notes.public
notes.added_at, notes.public
FROM users, notes
WHERE users.name=%s AND
notes.to_id=users.id AND
@ -216,7 +216,7 @@ class Notes(callbacks.Privmsg):
def notes(self, irc, msg, args):
"""takes no arguments
Retrieves all your unread notes.
"""
try:
@ -275,7 +275,7 @@ class Notes(callbacks.Privmsg):
ircutils.shrinkList(ids, ', ', 425)
ids.reverse()
irc.reply(msg, ', '.join(ids))
Class = Notes

View File

@ -179,7 +179,7 @@ class Quotes(ChannelDBHandler, callbacks.Privmsg):
irc.reply(msg, conf.replySuccess)
else:
irc.error(msg, conf.replyNoCapability % capability)
Class = Quotes
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -84,7 +84,7 @@ def configure(onStart, afterConnect, advanced):
if infocmd:
onStart.append('alias %s "rssinfo %s"' % (infocmd, url))
onStart.append('freeze %s' % infocmd)
class RSS(callbacks.Privmsg):
threaded = True
@ -114,7 +114,7 @@ class RSS(callbacks.Privmsg):
irc.error(msg, 'Error grabbing RSS feed')
return
irc.reply(msg, payload)
def rssinfo(self, irc, msg, args):
"""<url>
@ -142,7 +142,7 @@ class RSS(callbacks.Privmsg):
# The rest of the entries are all available in the channel key
response = 'Title: %s; URL: <%s>; ' \
'Description: %s; Last updated %s.' % (
info.get('title', 'unavailable').strip(),
info.get('title', 'unavailable').strip(),
info.get('link', 'unavailable').strip(),
info.get('description', 'unavailable').strip(),
when)

View File

@ -87,7 +87,7 @@ def configure(onStart, afterConnect, advanced):
while yn('Would like to relay between any more channels?') == 'y':
channel = anything('What channel?')
afterConnect.append('relayjoin %s' % channel)
class Relay(callbacks.Privmsg):
def __init__(self):
@ -99,7 +99,7 @@ class Relay(callbacks.Privmsg):
self.lastmsg = ircmsgs.ping('this is just a fake message')
self.channels = sets.Set()
self.abbreviations = {}
def inFilter(self, irc, msg):
if not isinstance(irc, irclib.Irc):
irc = irc.getRealIrc()
@ -110,7 +110,7 @@ class Relay(callbacks.Privmsg):
self.ircstates[irc].addMsg(irc, self.lastmsg)
self.lastmsg = msg
return msg
def startrelay(self, irc, msg, args):
"""<network abbreviation for current server>
@ -131,7 +131,7 @@ class Relay(callbacks.Privmsg):
def relayconnect(self, irc, msg, args):
"""<network abbreviation> <domain:port> (port defaults to 6667)
Connects to another network at <domain:port>. The network
abbreviation <network abbreviation> is used when relaying messages from
that network to other networks.
@ -267,7 +267,7 @@ class Relay(callbacks.Privmsg):
do312 = do311
do317 = do311
do319 = do311
def do318(self, irc, msg):
if not isinstance(irc, irclib.Irc):
irc = irc.getRealIrc()
@ -289,7 +289,7 @@ class Relay(callbacks.Privmsg):
s = '%s (%s) has been online since %s (idle for %s) and is on %s' % \
(nick, hostmask, signon, idle, channels)
replyIrc.reply(replyMsg, s)
def _formatPrivmsg(self, nick, network, msg):
# colorize nicks
nick = ircutils.mircColor(nick, *ircutils.canonicalColor(nick))
@ -358,7 +358,7 @@ class Relay(callbacks.Privmsg):
for otherIrc in self.ircs.itervalues():
if otherIrc != irc:
otherIrc.queueMsg(ircmsgs.privmsg(channel, s))
def doNick(self, irc, msg):
if self.started:
if not isinstance(irc, irclib.Irc):
@ -386,7 +386,7 @@ class Relay(callbacks.Privmsg):
for otherIrc in self.ircs.itervalues():
if otherIrc != irc:
otherIrc.queueMsg(ircmsgs.privmsg(channel, s))
def outFilter(self, irc, msg):
if not self.started:
return msg
@ -419,9 +419,9 @@ class Relay(callbacks.Privmsg):
if otherIrc != irc:
if otherIrc.state.getTopic(channel) != topic:
otherIrc.queueMsg(ircmsgs.topic(channel, topic))
return msg
Class = Relay
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -75,6 +75,6 @@ class ThreadedFunCommands(callbacks.Privmsg):
beta = version.strip()
irc.reply(msg, 'The latest stable kernel is %s; ' \
'the latest beta kernel is %s.' % (stable, beta))
Class = ThreadedFunCommands
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -119,7 +119,7 @@ class Topic(callbacks.Privmsg):
except IndexError:
irc.error(msg, 'That\'s not a valid index.')
return
def changetopic(self, irc, msg, args):
"""[<channel>] <number> <regexp>
@ -159,7 +159,7 @@ class Topic(callbacks.Privmsg):
topics.insert(number, newTopic)
newTopic = self.topicSeparator.join(topics)
irc.queueMsg(ircmsgs.topic(channel, newTopic))
def removetopic(self, irc, msg, args):
"[<channel>] (if not sent in the channel itself) <topic number>"
channel = privmsgs.getChannel(msg, args)

View File

@ -58,7 +58,7 @@ class TwistedCommands(callbacks.Privmsg):
failure.printDetailedTraceback()
irc.error(msg, failure.getErrorMessage())
return errback
dictnumberre = re.compile('^\d+:\s*(.*)$')
def dictCallback(self, irc, msg, word):
def formatDictResults(definitions):
@ -91,7 +91,7 @@ class TwistedCommands(callbacks.Privmsg):
deferred = dict.define('dict.org', 2628, 'wn', word)
deferred.addCallback(self.dictCallback(irc, msg, word))
deferred.addErrback(self.defaultErrback(irc, msg))
class TwistedRegexp(callbacks.PrivmsgRegexp):
def dccrecv(self, irc, msg, match):

View File

@ -187,8 +187,8 @@ class URLSnarfer(callbacks.Privmsg, ChannelDBHandler):
else:
(url,) = cursor.fetchone()
irc.reply(msg, url)
Class = URLSnarfer
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -61,7 +61,7 @@ def configure(onStart, afterConnect, advanced):
print 'choose to install it later, and then the module will'
print 'automatically work, as long as it is in the path of the'
print 'user that supybot runs under.'
print
print
print 'The "progstats" command can reveal potentially sensitive'
print 'information about your machine. Here\'s an example of its output:'
@ -80,7 +80,7 @@ def progstats():
os.getcwd(), " ".join(sys.argv),
sys.version.translate(string.ascii, '\r\n'))
return response
class Unix(callbacks.Privmsg):
def __init__(self):
@ -117,7 +117,7 @@ class Unix(callbacks.Privmsg):
except KeyError:
name = '(unknown)'
irc.reply(msg, '%s (#%s): %s' % (name, i, os.strerror(i)))
def progstats(self, irc, msg, args):
"""takes no arguments
@ -144,7 +144,7 @@ class Unix(callbacks.Privmsg):
salt = makeSalt()
irc.reply(msg, crypt.crypt(password, salt))
def spell(self, irc, msg, args):
def spell(self, irc, msg, args):
"""<word>
Returns the result of passing <word> to aspell/ispell. The results
@ -158,7 +158,7 @@ class Unix(callbacks.Privmsg):
return
self._spellWrite.write(word)
self._spellWrite.write('\n')
line = self._spellRead.readline()
line = self._spellRead.readline()
# aspell puts extra whitespace, ignore it
while line == '\n':
line = self._spellRead.readline()
@ -178,7 +178,7 @@ class Unix(callbacks.Privmsg):
else:
resp = 'Something unexpected was seen in the [ai]spell output.'
irc.reply(msg, resp)
Class = Unix
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -48,11 +48,11 @@ def configure(onStart, afterConnect, advanced):
class Utilities(callbacks.Privmsg):
def ignore(self, irc, msg, args):
pass
def shrink(self, irc, msg, args):
text = privmsgs.getArgs(args)
irc.reply(msg, text[:400])
def strjoin(self, irc, msg, args):
"<separator> <strings to join>"
sep = args.pop(0)
@ -128,7 +128,7 @@ class Utilities(callbacks.Privmsg):
irc.error(msg, 'Invalid regexp: %s' % e.args[0])
return
irc.reply(msg, ' '.join(r.findall(text)))
Class = Utilities
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -170,5 +170,5 @@ if __name__ == '__main__':
print 'You\'re done! Now run the bot with the command line:'
print 'src/bot.py conf/%s' % name
print
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -131,7 +131,7 @@ class MiscCommands(callbacks.Privmsg):
(command, simplehelp))
else:
irc.error(msg, 'That command has no help at all.')
def bug(self, irc, msg, args):
"""takes no arguments

View File

@ -126,7 +126,7 @@ class AsyncoreDriver(asynchat.async_chat, object):
def die(self):
self.close()
class ReplListener(asyncore.dispatcher, object):
def __init__(self, port=conf.telnetPort):
asyncore.dispatcher.__init__(self)

View File

@ -98,7 +98,7 @@ def reply(msg, s):
if len(m) > 512:
m = reply(msg, 'My response would\'ve been too long.')
return m
class RateLimiter:
lastRequest = {}
def __init__(self):
@ -232,8 +232,8 @@ def tokenize(s):
raise SyntaxError, str(e)
debug.msg('tokenize took %s seconds.' % (time.time() - start), 'verbose')
return args
class IrcObjectProxy:
def __init__(self, irc, msg, args):
@ -340,7 +340,7 @@ class CommandThread(threading.Thread):
self.irc = irc
self.msg = msg
self.setDaemon(True)
def run(self):
try:
start = time.time()
@ -356,7 +356,7 @@ class CommandThread(threading.Thread):
debug.recoverableException()
self.irc.error(self.msg, debug.exnToString(e))
class Privmsg(irclib.IrcCallback):
"""Base class for all Privmsg handlers."""
threaded = False
@ -508,7 +508,7 @@ class PrivmsgCommandAndRegexp(Privmsg):
method = getattr(self, name)
r = re.compile(method.__doc__, self.flags)
self.res.append((r, method))
def doPrivmsg(self, irc, msg):
if ircdb.checkIgnored(msg.prefix, msg.args[0]):
return
@ -528,10 +528,10 @@ class PrivmsgCommandAndRegexp(Privmsg):
if msg:
args = tokenize(s)
self.Proxy(irc, msg, args)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -188,3 +188,6 @@ driverModule = 'asyncoreDrivers'
###############################
###############################
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -45,7 +45,7 @@ except ImportError:
class conf:
logDir = '.'
detailedTracebacks = True
import world
###

View File

@ -284,5 +284,5 @@ def partition(p, L):
def flip((x, y)):
return (y, x)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -152,7 +152,7 @@ class UserCapabilitySet(CapabilitySet):
capability = ircutils.toLower(capability)
assert capability != '!owner', '"!owner" disallowed.'
CapabilitySet.add(self, capability)
class IrcUser(object):
"""This class holds the capabilities and authentications for a user.
"""
@ -498,7 +498,7 @@ def _x(capability, ret):
return not ret
else:
return ret
def checkCapability(hostmask, capability, users=users, channels=channels):
#debug.printf('*** checking %s for %s' % (hostmask, capability))
if world.startup:
@ -560,7 +560,7 @@ def checkCapability(hostmask, capability, users=users, channels=channels):
else:
#debug.printf('returning appropriate value given no good reason')
return _x(capability, conf.defaultAllow)
def checkCapabilities(hostmask, capabilities, requireAll=False):
"""Checks that a user has capabilities in a list.

View File

@ -227,7 +227,7 @@ class IrcState(IrcCommandDispatcher):
def __ne__(self, other):
return not self == other
def copy(self):
ret = self.__class__()
ret.history = copy.copy(self.history)

View File

@ -112,7 +112,7 @@ class IrcMsg(object):
else:
(self.nick, self.user, self.host) = (self.prefix,)*3
self.args = tuple(self.args)
def __str__(self):
if self._str is not None:
return self._str
@ -155,7 +155,7 @@ class IrcMsg(object):
self._len += len(arg) + 1 # Remember space prior to the arg.
self._len += 2 # For colon before the prefix and before the last arg.
return self._len
def __eq__(self, other):
return hash(self) == hash(other) and \
self.command == other.command and \
@ -249,7 +249,7 @@ def prettyPrint(msg, addRecipients=False):
elif msg.command == 'TOPIC':
s = '*** %s changes topic to %s' % (nickorprefix(), msg.args[1])
return s
###
# Various IrcMsg functions
###

View File

@ -309,7 +309,7 @@ class IrcString(str):
def __str__(self):
return str(self.original)
def __eq__(self, s):
try:
return toLower(s) == self.lowered

View File

@ -100,7 +100,7 @@ def getKeywordArgs(irc, msg, d=None):
args.append(left)
del args[0] # The command name itself.
return (args, d)
def checkCapability(f, capability):
def newf(self, irc, msg, args):
if ircdb.checkCapability(msg.prefix, capability):
@ -225,7 +225,7 @@ class OwnerCommands(CapabilityCheckingPrivmsg):
"""
world.upkeep()
irc.reply(msg, conf.replySuccess)
def set(self, irc, msg, args):
"""<name> <value>
@ -280,7 +280,7 @@ class OwnerCommands(CapabilityCheckingPrivmsg):
world.superReload(__import__(name))
irc.reply(msg, conf.replySuccess)
'''
def reload(self, irc, msg, args):
"""<callback name>
@ -307,7 +307,7 @@ class OwnerCommands(CapabilityCheckingPrivmsg):
irc.error(msg, 'No plugin %s exists.' % name)
else:
irc.error(msg, 'There was no callback %s.' % name)
def unload(self, irc, msg, args):
"""<callback name>

View File

@ -47,7 +47,7 @@ class RTuple(tuple):
return not tuple.__le__(self, other)
def __cmp__(self, other):
return -1*tuple.__cmp__(self, other)
class Schedule(drivers.IrcDriver):
def __init__(self):
drivers.IrcDriver.__init__(self)

View File

@ -66,10 +66,10 @@ class RingBuffer(object):
return False
return True
return False
def __nonzero__(self):
return len(self) > 0
def __contains__(self, elt):
return elt in self.L
@ -88,7 +88,7 @@ class RingBuffer(object):
def extend(self, seq):
for elt in seq:
self.append(elt)
def __getitem__(self, idx):
if self.full:
oidx = idx
@ -226,7 +226,7 @@ class queue(object):
return self.front[-(idx+1)]
else:
return self.back[(idx-len(self.front))]
def __setitem__(self, oidx, value):
if len(self) == 0:
raise IndexError, 'queue index out of range'
@ -272,7 +272,7 @@ class queue(object):
self.front = L
self.back = []
class MaxLengthQueue(queue):
__slots__ = ('length',)
def __init__(self, length, seq=()):
@ -285,7 +285,7 @@ class MaxLengthQueue(queue):
def __setstate__(self, (length, q)):
self.length = length
queue.__setstate__(self, q)
def enqueue(self, elt):
queue.enqueue(self, elt)
if len(self) > self.length:

View File

@ -87,7 +87,7 @@ class SupyIrcProtocol(LineReceiver):
self.transport.loseConnection()
reconnect = die
class SupyReconnectingFactory(ReconnectingClientFactory):
maxDelay = 600
@ -96,7 +96,7 @@ class SupyReconnectingFactory(ReconnectingClientFactory):
self.irc = irc
self.server = (server, port)
reactor.connectTCP(server, port, self)
class MyShell(Shell):
def checkUserAndPass(self, username, password):
@ -112,13 +112,13 @@ class MyShell(Shell):
return False
except KeyError:
return False
class MyShellFactory(ShellFactory):
protocol = MyShell
if conf.telnetEnable and __name__ != '__main__':
reactor.listenTCP(conf.telnetPort, MyShellFactory())
Driver = SupyReconnectingFactory

View File

@ -160,8 +160,8 @@ class PluginTestCase(unittest.TestCase):
self.assertEqual(len(expectedResponses), len(responses))
for (m, expected) in zip(responses, expectedResponses):
self.assertEqual(m.args[1], expected)
if __name__ == '__main__':
world.testing = True
if len(sys.argv) > 1:

View File

@ -78,7 +78,7 @@ class FunCommandsTest(PluginTestCase):
def testPydoc(self):
self.assertNotError('pydoc str')
self.assertError('pydoc foobar')
def testOrd(self):
for c in map(chr, range(256)):
i = ord(c)

View File

@ -103,7 +103,7 @@ class UserCapabilitySetTestCase(unittest.TestCase):
d.add('owner')
self.failUnless(d.check('owner'))
class CapabilitySetTestCase(unittest.TestCase):
def testContains(self):
@ -119,7 +119,7 @@ class CapabilitySetTestCase(unittest.TestCase):
s.add('!foo')
self.failUnless('foo' in s)
self.failUnless('!foo' in s)
def testCheck(self):
s = ircdb.CapabilitySet()
self.assertRaises(KeyError, s.check, 'foo')
@ -146,7 +146,7 @@ class CapabilitySetTestCase(unittest.TestCase):
s.add('foo')
self.failUnless(s.check('foo'))
self.failIf(s.check('!foo'))
class UserCapabilitySetTestCase(unittest.TestCase):
def testOwner(self):
@ -179,7 +179,7 @@ class IrcUserTestCase(unittest.TestCase):
u.addCapability('owner')
self.failUnless(u.checkCapability('foo'))
self.failIf(u.checkCapability('!foo'))
def testInitCapabilities(self):
u = ircdb.IrcUser(capabilities=['foo'])
self.failUnless(u.checkCapability('foo'))
@ -211,7 +211,7 @@ class IrcUserTestCase(unittest.TestCase):
u = ircdb.IrcUser(ignore=True)
self.failIf(u.checkCapability('foo'))
self.failUnless(u.checkCapability('!foo'))
class IrcChannelTestCase(unittest.TestCase):
def testInit(self):
c = ircdb.IrcChannel()
@ -240,7 +240,7 @@ class IrcChannelTestCase(unittest.TestCase):
def testLobotomized(self):
c = ircdb.IrcChannel(lobotomized=True)
self.failUnless(c.checkIgnored(''))
def testIgnored(self):
prefix = 'foo!bar@baz'
banmask = ircutils.banmask(prefix)
@ -262,10 +262,10 @@ class UsersDictionaryTestCase(unittest.TestCase):
fd.write('{}\n')
fd.close()
self.users = ircdb.UsersDictionary(self.filename)
def tearDown(self):
os.remove(self.filename)
def testGetSetDelUser(self):
self.assertRaises(KeyError, self.users.getUser, 'foo')
self.assertRaises(KeyError, self.users.getUser, 'foo!bar@baz')
@ -283,7 +283,7 @@ class UsersDictionaryTestCase(unittest.TestCase):
u.removeHostmask(banmask)
u.addHostmask('*!*@*')
self.assertRaises(ValueError, self.users.setUser, 'biff', u)
class CheckCapabilityTestCase(unittest.TestCase):
filename = 'CheckCapabilityTestCase.conf'
@ -334,7 +334,7 @@ class CheckCapabilityTestCase(unittest.TestCase):
self.users.setUser('antichanfoo', antichanfoo)
channel = ircdb.IrcChannel()
self.channels.setChannel(self.channel, channel)
def tearDown(self):
os.remove(self.filename)
@ -383,10 +383,10 @@ class CheckCapabilityTestCase(unittest.TestCase):
def testJustChanFoo(self):
self.channels.setChannel(self.channel, self.channelnothing)
self.failUnless(self.checkCapability(self.justchanfoo, self.chancap))
self.failIf(self.checkCapability(self.justchanfoo, self.antichancap))
self.failIf(self.checkCapability(self.justchanfoo, self.antichancap))
self.channelnothing.defaultAllow = not self.channelnothing.defaultAllow
self.failUnless(self.checkCapability(self.justchanfoo, self.chancap))
self.failIf(self.checkCapability(self.justchanfoo, self.antichancap))
self.failIf(self.checkCapability(self.justchanfoo, self.antichancap))
self.channels.setChannel(self.channel, self.channelanticap)
self.failUnless(self.checkCapability(self.justchanfoo, self.chancap))
self.failIf(self.checkCapability(self.justchanfoo, self.antichancap))

View File

@ -50,7 +50,7 @@ class IrcMsgQueueTestCase(unittest.TestCase):
def testEmpty(self):
q = irclib.IrcMsgQueue()
self.failIf(q)
def testEnqueueDequeue(self):
q = irclib.IrcMsgQueue()
q.enqueue(self.msg)
@ -131,7 +131,7 @@ class ChannelTestCase(unittest.TestCase):
self.failIf('quuz' in c.halfops)
self.failIf('quuz' in c.voices)
class IrcStateTestCase(unittest.TestCase):
class FakeIrc:
nick = 'nick'
@ -171,11 +171,11 @@ class IrcStateTestCase(unittest.TestCase):
self.assertEqual(state1, state2)
except Exception:
pass
"""
def testChannels(self):
channel =
channel =
state = irclib.IrcState()
state.addMsg(self.irc, ircmsgs.join('#foo'))
"""

View File

@ -126,7 +126,7 @@ class FunctionsTestCase(unittest.TestCase):
withException = ircmsgs.ban(channel, ban, exception)
self.assertEqual(ircutils.separateModes(withException.args[1:]),
[('+b', ban), ('+e', exception)])
def testBans(self):
channel = '#osu'
bans = ['*!*@*', 'jemfinch!*@*']

View File

@ -84,14 +84,14 @@ class FunctionsTestCase(unittest.TestCase):
self.assertEqual('\x03,5foo\x03', ircutils.mircColor(s, bg='brown'))
self.assertEqual('\x036,7foo\x03',
ircutils.mircColor(s, bg='orange', fg='purple'))
def testMircColors(self):
# Make sure all (k, v) pairs are also (v, k) pairs.
for (k, v) in ircutils.mircColors.items():
if k:
self.assertEqual(ircutils.mircColors[v], k)
def testSafeArgument(self):
s = 'I have been running for 9 seconds'
bolds = ircutils.bold(s)

View File

@ -63,8 +63,8 @@ class TestSchedule(unittest.TestCase):
self.assertEqual(i[0], 11)
time.sleep(3)
self.assertEqual(i[0], 11)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -183,7 +183,7 @@ class RingBufferTestCase(unittest.TestCase):
b = RingBuffer(100, range(10))
b1 = RingBuffer(10, range(10))
self.failIf(b == b1)
def testIter(self):
b = RingBuffer(3, range(3))
L = []
@ -214,7 +214,7 @@ class QueueTest(unittest.TestCase):
self.assertRaises(IndexError, q.__getitem__, -(n+1))
self.assertRaises(IndexError, q.__getitem__, n)
self.assertEqual(q[3:7], queue([3, 4, 5, 6]))
def testSetitem(self):
q1 = queue()
self.assertRaises(IndexError, q1.__setitem__, 0, 0)
@ -224,7 +224,7 @@ class QueueTest(unittest.TestCase):
for (i, elt) in enumerate(q2):
q2[i] = elt*2
self.assertEqual([x*2 for x in q1], list(q2))
def testNonzero(self):
q = queue()
self.failIf(q, 'queue not zero after initialization')
@ -301,7 +301,7 @@ class QueueTest(unittest.TestCase):
self.assertEqual(q, eval(repr(q)), 'repr doesn\'t eval to same queue')
q.enqueue((1,))
self.assertEqual(q, eval(repr(q)), 'repr doesn\'t eval to same queue')
def testEnqueueDequeue(self):
q = queue()
self.assertRaises(IndexError, q.dequeue)
@ -360,7 +360,7 @@ class MaxLengthQueueTestCase(unittest.TestCase):
q = MaxLengthQueue(3, (1, 2, 3))
self.assertEqual(list(q), [1, 2, 3])
self.assertRaises(TypeError, MaxLengthQueue, 3, 1, 2, 3)
def testMaxLength(self):
q = MaxLengthQueue(3)
q.enqueue(1)