def get_stock_codes(self, cached=True, as_json=False): """ returns a dictionary with key as stock code and value as stock name. It also implements cache functionality and hits the server only if user insists or cache is empty :return: dict """ url = self.stocks_csv_url req = Request(url, None, self.headers) res_dict = {} if cached is not True or self.__CODECACHE__ is None: # raises HTTPError and URLError res = self.opener.open(req) if res is not None: # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) for line in res.read().split('\n'): if line != '' and re.search(',', line): (code, name) = line.split(',')[0:2] res_dict[code] = name # else just skip the evaluation, line may not be a valid csv else: raise Exception('no response received') self.__CODECACHE__ = res_dict return self.render_response(self.__CODECACHE__, as_json)
def get_quote(self, code, as_json=False): """ gets the quote for a given stock code :param code: :return: dict or None :raises: HTTPError, URLError """ code = code.upper() if self.is_valid_code(code): url = self.build_url_for_quote(code) req = Request(url, None, self.headers) # this can raise HTTPError and URLError, but we are not handling it # north bound APIs should use it for exception handling res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) # Now parse the response to get the relevant data match = re.search(\ r'\{<div\s+id="responseDiv"\s+style="display:none">\s+(\{.*?\{.*?\}.*?\})', res.read(), re.S ) # ast can raise SyntaxError, let's catch only this error try: buffer = match.group(1) buffer = js_adaptor(buffer) response = self.clean_server_response(ast.literal_eval(buffer)['data'][0]) except SyntaxError as err: raise Exception('ill formatted response') else: return self.render_response(response, as_json) else: return None
def get_index_quote(self, code, as_json=False): """ params: code : string index code as_json: True|False returns: a dict | json quote for the given index """ url = self.index_url if self.is_valid_index(code): req = Request(url, None, self.headers) # raises HTTPError and URLError resp = self.opener.open(req) resp = byte_adaptor(resp) resp_list = json.load(resp)['data'] # this is list of dictionaries resp_list = [self.clean_server_response(item) for item in resp_list] # search the right list element to return search_flag = False for item in resp_list: if item['name'] == code.upper(): search_flag = True break return self.render_response(item, as_json) if search_flag else None
def test_byte_adaptor(self): if six.PY2: from StringIO import StringIO buffer = 'nsetools' fbuffer = StringIO(buffer) else: from io import BytesIO buffer = b'nsetools' fbuffer = BytesIO(buffer) ret_file_buffer = byte_adaptor(fbuffer) self.assertIsInstance(ret_file_buffer, six.StringIO)
def get_index_list(self, as_json=False): """ get list of indices and codes params: as_json: True | False returns: a list | json of index codes """ url = self.index_url req = Request(url, None, self.headers) # raises URLError or HTTPError resp = self.opener.open(req) resp = byte_adaptor(resp) resp_list = json.load(resp)['data'] index_list = [str(item['name']) for item in resp_list] return self.render_response(index_list, as_json)
def get_top_gainers(self, as_json=False): """ :return: a list of dictionaries containing top gainers of the day """ url = self.top_gainer_url req = Request(url, None, self.headers) # this can raise HTTPError and URLError res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res_dict = json.load(res) # clean the output and make appropriate type conversions res_list = [self.clean_server_response(item) for item in res_dict['data']] return self.render_response(res_list, as_json)
def _get_json_response_from_url(self, url, as_json): """ :return: a list of dictionaries containing the response got back from url """ req = Request(url, None, self.headers) # this can raise HTTPError and URLError res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res_dict = json.load(res) # clean the output and make appropriate type conversions res_list = [self.clean_server_response(item) for item in res_dict['data']] return self.render_response(res_list, as_json)
def get_advances_declines(self, as_json=False): """ :return: a list of dictionaries with advance decline data :raises: URLError, HTTPError """ url = self.advances_declines_url req = Request(url, None, self.headers) # raises URLError or HTTPError resp = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object resp = byte_adaptor(resp) resp_dict = json.load(resp) resp_list = [self.clean_server_response(item) for item in resp_dict['data']] return self.render_response(resp_list, as_json)
def _get_json_response_from_url(self, url, as_json): """ :return: a list of dictionaries containing the response got back from url """ req = Request(url, None, self.headers) # this can raise HTTPError and URLError res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res_dict = json.load(res) # clean the output and make appropriate type conversions res_list = [ self.clean_server_response(item) for item in res_dict['data'] ] return self.render_response(res_list, as_json)
def get_top_fno_losers(self, as_json=False): """ :return: a list of dictionaries containing top losers of the day """ url = self.top_fno_loser_url req = Request(url, None, self.headers) # this can raise HTTPError and URLError res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res_dict = json.load(res) # clean the output and make appropriate type conversions res_list = [self.clean_server_response(item) for item in res_dict['data']] return self.render_response(res_list, as_json)
def get_index_list(self, cached=True, as_json=False): """ get list of indices and codes params: as_json: True | False returns: a list | json of index codes """ if cached is not True or self.__INDEXLISTCACHE__ is None: url = self.index_url req = Request(url, None, self.headers) # raises URLError or HTTPError resp = self.opener.open(req) resp = byte_adaptor(resp) resp_list = json.load(resp)['data'] self.__INDEXLISTCACHE__ = [str(item['name']) for item in resp_list] return self.render_response(self.__INDEXLISTCACHE__, as_json)
def read_url(url, headers): """ Reads the url, processes it and returns a StringIO object to aid reading :Parameters: url: str the url to request and read from headers: dict The right set of headers for requesting from http://nseindia.com :returns: _io.StringIO object of the response """ request = Request(url, None, headers) response = __opener__().open(request) if response is not None: return byte_adaptor(response) else: raise Exception('No response received')
def get_quote(self, code, as_json=False): """ gets the quote for a given stock code :param code: :return: dict or None :raises: HTTPError, URLError """ code = code.upper() if self.is_valid_code(code): url = self.build_url_for_quote(code) req = Request(url, None, self.headers) # this can raise HTTPError and URLError, but we are not handling it # north bound APIs should use it for exception handling res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res = res.read() # Now parse the response to get the relevant data match = re.search( r'<div\s+id="responseDiv"\s+style="display:none">(.*?)</div>', res, re.S ) try: buffer = match.group(1).strip() # commenting following two lines because now we are not using # ast and instead relying on json's ability to do parsing. # Should be much faster and more reliable. # buffer = js_adaptor(buffer) # response = self.clean_server_response( # ast.literal_eval(buffer)['data'][0] # ) response = self.clean_server_response( json.loads(buffer)['data'][0]) except SyntaxError as err: raise Exception(f'ill formatted response {err}') else: return self.render_response(response, as_json) else: return None
def get_quote(self, code, as_json=False): """ gets the quote for a given stock code :param code: :return: dict or None :raises: HTTPError, URLError """ code = code.upper() if self.is_valid_code(code): url = self.build_url_for_quote(code) req = Request(url, None, self.headers) # this can raise HTTPError and URLError, but we are not handling it # north bound APIs should use it for exception handling res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res = res.read() # Now parse the response to get the relevant data match = re.search(\ r'<div\s+id="responseDiv"\s+style="display:none">(.*?)</div>', res, re.S ) try: buffer = match.group(1).strip() # commenting following two lines because now we are not using ast and instead # relying on json's ability to do parsing. Should be much faster and more # reliable. #buffer = js_adaptor(buffer) #response = self.clean_server_response(ast.literal_eval(buffer)['data'][0]) response = self.clean_server_response(json.loads(buffer)['data'][0]) except SyntaxError as err: raise Exception('ill formatted response') else: return self.render_response(response, as_json) else: return None
def get_OPTquote(self, code, expiry, opttype, strike, as_json=False): """ gets the quote for a given stock code :param code: :return: dict or None :raises: HTTPError, URLError """ code = code.upper() expiry = expiry.upper() opttype = opttype.upper() if self.is_valid_code(code): url = self.build_url_for_OPTquote(code, expiry, opttype, strike) req = Request(url, None, self.headers) # this can raise HTTPError and URLError, but we are not handling it # north bound APIs should use it for exception handling res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) res = res.read() # Now parse the response to get the relevant data try: # buffer = res.group(1).strip() # commenting following two lines because now we are not using ast and instead # relying on json's ability to do parsing. Should be much faster and more # reliable. #buffer = js_adaptor(buffer) #response = self.clean_server_response(ast.literal_eval(buffer)['data'][0]) response = self.clean_server_response(json.loads(res)['data'][0]) except SyntaxError as err: raise Exception('ill formatted response') else: return self.render_response(response, as_json) else: return None
def get_quote(self, code, as_json=False): """ gets the quote for a given stock code :param code: :return: dict or None :raises: HTTPError, URLError """ code = code.upper() if self.is_valid_code(code): url = self.build_url_for_quote(code) req = Request(url, None, self.headers) # this can raise HTTPError and URLError, but we are not handling it # north bound APIs should use it for exception handling res = self.opener.open(req) # for py3 compat covert byte file like object to # string file like object res = byte_adaptor(res) # Now parse the response to get the relevant data match = re.search(\ r'\{<div\s+id="responseDiv"\s+style="display:none">\s+(\{.*?\{.*?\}.*?\})', res.read(), re.S ) # ast can raise SyntaxError, let's catch only this error try: buffer = match.group(1) buffer = js_adaptor(buffer) response = self.clean_server_response( ast.literal_eval(buffer)['data'][0]) except SyntaxError as err: raise Exception('ill formatted response') else: return self.render_response(response, as_json) else: return None
def test_byte_adaptor(self): from io import BytesIO buffer = b'nsetools' fbuffer = BytesIO(buffer) ret_file_buffer = byte_adaptor(fbuffer) self.assertIsInstance(ret_file_buffer, six.StringIO)