📄 __init__.py
字号:
"""Initialize the valid params, this is a virtual function and should be overriden properly.""" err = """Yahoo Search Service class %s must implement a \_init_valid_params()""" % (self.svc_name) raise ClassError(err) def reset(self): """Reset all the parameter values for the object instance.""" self._params = {} def _get_svc_name(self): """Get the descriptive service name.""" return self._service['name'] def _set_svc_name(self, value): """Set the descriptive service name.""" self._service['name'] = value svc_name = property(_get_svc_name, _set_svc_name, None, "Descriptive name of the service") def _get_svc_protocol(self): """Get the service protocol (e.g. HTTP).""" return self._service['protocol'] def _set_svc_protocol(self, value): """Set the service protocol (must be supported).""" self._service['protocol'] = value svc_protocol = property(_get_svc_protocol, _set_svc_protocol, None, "Service protocol (e.g. HTTP)") def _get_svc_service(self): """Get the URL path for the service.""" return self._service['service'] def _set_svc_service(self, value): """Set the URL path for the service.""" self._service['service'] = value svc_service = property(_get_svc_service, _set_svc_service, None, "Service path") def _get_svc_server(self): """Get the service server name or IP.""" return self._service['server'] def _set_svc_server(self, value): """Set the service server name or IP.""" self._service['server'] = value svc_server = property(_get_svc_server, _set_svc_server, None, "Service server name or IP") def _get_svc_version(self): """Get the service version string.""" return self._service['version'] def _set_svc_version(self, value): """Set the service version string.""" self._service['version'] = value svc_version = property(_get_svc_version, _set_svc_version, None, "Service version string") def _get_app_id(self): """Get the application ID.""" return self._app_id def _set_app_id(self, app_id): """Set the application ID, which is required.""" if isinstance(app_id, types.StringTypes): self._app_id = app_id else: raise ValueError("""`app_id' can contain \a-zA-Z0-9 _()\[\]*+\-=,.:\\\@ (8-40 char long)""") app_id = property(_get_app_id, _set_app_id, None, "Application ID (issued by Yahoo), same ass appid") appid = property(_get_app_id, _set_app_id, None, "Application ID (issued by Yahoo)") # Manage service parameters def set_params(self, args): """Set one or several query parameters from a dictionary""" for (param, value) in args.items(): self.set_param(param, value) def get_param(self, param): """Get the value of a query parameter, or the default value if unset""" if not self._valid_params.has_key(param): err = "`%s' is not a valid parameter for `%s'" % ( param, self._service['name']) raise ParameterError(err) if self._params.has_key(param): return self._params[param] else: return self._valid_params[param][1] # # The valid_params is a list with the following elements: # [0] - Allowed data type (e.g. types.StringTypes) # [1] - Default value (e.g. 10) # [2] - Data conversion/casting function (e.g. int) # [3] - List of valid values -or- validation function # [4] - Help text for error messages # [5] - Boolean indicating if the parameter is required # def set_param(self, param, value): """Set the value of a query parameter""" if not self._valid_params.has_key(param): err = "`%s' is not a valid parameter for `%s'" % ( param, self._service['name']) raise ParameterError(err) pinfo = self._valid_params[param] if value is None: err = "`%s' can not have an undefined value" % (param) raise ValueError(err) # Do explicit type conversions (if possible) if pinfo[2] is not None: try: if isinstance(value, (types.ListType, types.TupleType)): value = [pinfo[2](val) for val in value] # ToDo XXX: Should we make sure each value is unique? else: value = pinfo[2](value) except ValueError: value = value # Check the type validity of the value err = False if isinstance(value, (types.ListType, types.TupleType)): for val in value: if not isinstance(val, pinfo[0]): err = True break elif not isinstance(value, pinfo[0]): err = True if err: raise TypeError("`%s' only takes values of type %s" % ( param, str(pinfo[0]))) # Check validity of the value (if possible) err = False if callable(pinfo[3]): if isinstance(value, (types.ListType, types.TupleType)): for val in value: if not pinfo[3](val): err = True break else: if not pinfo[3](value): err = True elif isinstance(pinfo[3], (types.TupleType, types.ListType)): if isinstance(value, (types.ListType, types.TupleType)): for val in value: if not val in pinfo[3]: err = True break elif not value in pinfo[3]: err = True if err: if pinfo[4] is not None: hlp = pinfo[4] else: hlp = str(pinfo[3]) raise ValueError("`%s' only handles values in: %s" % (param, hlp)) # Update the parameter only if it's different from the default if value != pinfo[1]: self._params[param] = value elif self._params.has_key(param): self._params.pop(param) def get_valid_params(self): """Return a list of all valid parameters for this search""" return self._valid_params.keys() def missing_params(self): """Validate that the search object is propertly setup with all required parameters etc. This is called automatically before a search is actually performed, but you can also call it manually if desired. It will return a list of zero or more paramters that are missing. """ ret = [] for (param, pinfo) in self._valid_params.items(): if pinfo[5]: if (not self._params.has_key(param) or not self._params[param]): ret.append(param) # Check "require_oneof" list, if necessary if len(ret) == 0: for param in self._require_oneof_params: if self._params.has_key(param): return [] return self._require_oneof_params else: return ret def _get_languages(self): """Get the list of all supported languages.""" return LANGUAGES languages = property(_get_languages, None, None, "List of all supported languages") def _get_countries(self): """Get the list of all supported contry codes.""" return COUNTRIES countries = property(_get_countries, None, None, "List of all supported county codes") def _get_regions(self): """Get the list of all supported region codes.""" return REGIONS regions = property(_get_regions, None, None, "List of all supported region codes") def _get_cc_licenses(self): """Get the list of all supported CC licenses.""" return CC_LICENSES cc_licenses = property(_get_cc_licenses, None, None, "List of all supported Creative Commons licenses") def _get_subscriptions(self): """Get the list of supported premium subscriptions.""" return SUBSCRIPTIONS subscriptions = property(_get_subscriptions, None, None, "List of all supported premium subscriptions") # Manage (install) the Opener, XML parser and result factory (parser) def install_opener(self, opener): """Install a URL opener (for use with urllib2), overriding the default opener. This is rarely required. """ self._urllib_opener = opener def install_xml_parser(self, xml_parser): """Install an XML parser that will be used for all results for this object. The parser is expected to "read" the data from the supplied stream argument. To uninstall the parser (e.g. to make sure we return raw XML data) simply call this method with an argument of None. """ self._default_xml_parser = xml_parser self._xml_parser = xml_parser def install_result_factory(self, result_factory): """Install a python class (not an instance!) that should be used as a factory for creating result(s) objects. """ self._result_factory = result_factory # Methods working on connection handling etc. def encode_params(self): """URL encode the list of parameter values.""" params = self._params.copy() params.update({'appid' : self._app_id}) return urllib.urlencode(params, 1) def get_url(self, with_params=True): """Return the URL for this request object""" url = "%s://%s/%s/%s/%s" % (self._service['protocol'], self._service['server'], self._service['service'], self._service['version'], self._service['name']) if with_params: return "%s?%s" % (url, self.encode_params()) else: return url def open(self, opener=None, retries=2): """Open a connection to the webservice server, and request the URL. The return value is a "stream", which can be read calling the read(), readline() or readlines() methods. If you override this method, please make sure to call the missing_params() method before you try to send a request to the Web server. """ missing = self.missing_params() if missing: if len(missing) > 1: err = "Missing these parameters: `%s'" % str(missing) else: err = "Missing the parameter `%s'" % missing[0] raise ParameterError(err) if opener is not None: urllib2.install_opener(opener) elif self._urllib_opener is not None: urllib2.install_opener(self._urllib_opener) if self.METHOD == "POST": url = self.get_url(with_params=False) data = self.encode_params() else: url = self.get_url(with_params=True) data = None self._debug_msg("Opening URL = %s", debug.DEBUG_LEVELS['HTTP'], url) if data: self._debug_msg("POSTing data = %s", debug.DEBUG_LEVELS['HTTP'], data) try: resp = urllib2.urlopen(url, data) except urllib2.HTTPError, err: if err.code == 503: retries -= 1 if retries >= 0: self._debug_msg("Retrying open(), URL = %s", debug.DEBUG_LEVELS['HTTP'], url) time.sleep(0.05) return self.open(opener, retries=retries) raise ServerError("""Internal WebService error, temporarily \unavailable""") else: raise SearchError(err) raise ServerError("WebService server unavailable") return resp def get_results(self, stream=None, xml_parser=None, close=True): """Read the stream (if provided) and either return the raw XML, or send the data to the provided XML parser for further processing. If no stream is provided, it will call the open() method using the default opener. The stream will be closed upon return from this method, unless the close=False is passed as an argument. """ self._debug_msg("VALID_PARAMS = %s", debug.DEBUG_LEVELS['PARAMS'], self._valid_params.keys()) if stream is None: stream = self.open() if xml_parser is None: xml_parser = self._xml_parser if xml_parser is not None: res = xml_parser(stream) try: self._debug_msg("XML results are:\n%s", debug.DEBUG_LEVELS['RAWXML'], res.toprettyxml()) except AttributeError: pass else: res = "".join(stream.readlines()) if close: stream.close() return res def parse_results(self, xml=None): """Get the result from the request, and instantiate the appropriate result class. This class will be populated with all the data from the XML object. """ if self._result_factory is None: return None if xml is None: xml = self.get_results() res = self._result_factory(service=self) res.parse_results(xml) return res def _get_debug_level(self): """Get the current debug level.""" return self._debug_level def _set_debug_level(self, level): """Set the new debug level to be used.""" self._debug_level = level debug_level = property(_get_debug_level, _set_debug_level, None, "Set and modify the debug level")## Basic parameters, supported by all regular search classes#class _BasicSearch(_Search): """Yahoo Search WebService - basic params service Setup the basic CGI parameters that all (normal) search services supports. This is used by most services (classes) to provision for the basic parameters they all use. """ def _init_valid_params(self): """Initialize the set of valid parameters.""" self._valid_params.update({ "query" : (types.StringTypes, None, None, None, None, True), "results" : (types.IntType, 10, int, lambda x: x > -1 and x < 51, "the range 1 to 50", False), "start" : (types.IntType, 1, int, lambda x: x > -1 and x < 1001, None, False), })## Common search parameters, shared by several packages, but not all.#class _CommonSearch(_Search): """Yahoo Search WebService - common params service Several search services share a few non-basic parameters, so this sub-class of _BasicParams saves some typing. """ def _init_valid_params(self): """Initialize the set of valid parameters.""" self._valid_params.update({ "query" : (types.StringTypes, None, None, None, None, True), "results" : (types.IntType, 10, int, lambda x: x > -1 and x < 51, "the range 1 to 50", False), "start" : (types.IntType, 1, int, lambda x: x > -1 and x < 1001, None, False), "type" : (types.StringTypes, "any", str.lower, ("all", "any", "phrase"), None, False), "adult_ok" : (types.IntType, None, int, (1,), None, False), })## local variables:# mode: python# indent-tabs-mode: nil# py-indent-offset: 4# end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -