diff --git a/hexonet/apiconnector/__init__.py b/hexonet/apiconnector/__init__.py index a785fd3..bbc18d4 100755 --- a/hexonet/apiconnector/__init__.py +++ b/hexonet/apiconnector/__init__.py @@ -4,24 +4,24 @@ __version__ = '1.0.0' name = "apiconnector" -def connect(login=None, password=None, url=None, entity=None, user=None, role=None, config=None): - """ - Returns an instance of apiconnector.Connection - """ - if config == None: - config = {} - if login != None: - config['login'] = login - if password != None: - config['password'] = password - if url != None: - config['url'] = url - if entity != None: - config['entity'] = entity - if user != None: - config['user'] = user - if role != None: - config['role'] = role - return Connection(config) +def connect(login=None, password=None, url=None, entity=None, user=None, role=None, config=None): + """ + Returns an instance of apiconnector.Connection + """ + if config is None: + config = {} + if login is not None: + config['login'] = login + if password is not None: + config['password'] = password + if url is not None: + config['url'] = url + if entity is not None: + config['entity'] = entity + if user is not None: + config['user'] = user + if role is not None: + config['role'] = role + return Connection(config) diff --git a/hexonet/apiconnector/connection.py b/hexonet/apiconnector/connection.py index d4ac371..6b91088 100755 --- a/hexonet/apiconnector/connection.py +++ b/hexonet/apiconnector/connection.py @@ -8,55 +8,56 @@ # Fall back to Python 2's urllib2 from urllib2 import urlopen try: - # For Python 3.0 and later - from urllib import parse as urlparse + # For Python 3.0 and later + from urllib import parse as urlparse except ImportError: - # Fall back to Python 2 - from urlparse import urlparse + # Fall back to Python 2 + from urlparse import urlparse """ APICONNECTOR Connection """ + + class Connection: - def __init__(self, config): - """ - Constructor - """ - self._config = config - - def call_raw_http(self, command, config = None): - - """ - Make a curl API call over HTTP(S) and returns the response as a string - """ - post = {} - if ('login' in self._config): - post['s_login'] = self._config['login'] - if ('password' in self._config): - post['s_pw'] = self._config['password'] - if ('entity' in self._config): - post['s_entity'] = self._config['entity'] - if ('user' in self._config): - post['s_user'] = self._config['user'] - if ('role' in self._config): - post['s_login'] = self._config['login'] + "!" + self._config['role'] - - post['s_command'] = apiconnector.util.command_encode(command) - post = urlparse.urlencode(post) - response = urlopen(self._config['url'], post.encode('UTF-8')) - content = response.read() - return content - - def call_raw(self, command, config = None): - """ - Make a curl API call and returns the response as a string - """ - return self.call_raw_http(command, config) - - def call(self, command, config = None): - """ - Make a curl API call and returns the response as a response object - """ - return Response(self.call_raw(command, config)) + def __init__(self, config): + """ + Constructor + """ + self._config = config + + def call_raw_http(self, command, config=None): + """ + Make a curl API call over HTTP(S) and returns the response as a string + """ + post = {} + if ('login' in self._config): + post['s_login'] = self._config['login'] + if ('password' in self._config): + post['s_pw'] = self._config['password'] + if ('entity' in self._config): + post['s_entity'] = self._config['entity'] + if ('user' in self._config): + post['s_user'] = self._config['user'] + if ('role' in self._config): + post['s_login'] = self._config['login'] + "!" + self._config['role'] + + post['s_command'] = apiconnector.util.command_encode(command) + post = urlparse.urlencode(post) + response = urlopen(self._config['url'], post.encode('UTF-8')) + content = response.read() + return content + + def call_raw(self, command, config=None): + """ + Make a curl API call and returns the response as a string + """ + return self.call_raw_http(command, config) + + def call(self, command, config=None): + """ + Make a curl API call and returns the response as a response object + """ + return Response(self.call_raw(command, config)) diff --git a/hexonet/apiconnector/response.py b/hexonet/apiconnector/response.py index 71c9eb2..03f8ea3 100755 --- a/hexonet/apiconnector/response.py +++ b/hexonet/apiconnector/response.py @@ -4,223 +4,221 @@ APICONNECTOR Response """ + + class Response: - def __init__(self, response): - """ - Constructor - """ - self._response_string = None - self._response_hash = None - self._response_list_hash = None - - #try/except to support old versions of python (python2.5) - try: - if type(response) == bytes: - response = response.decode("utf-8") - self._response_string = response - except UnicodeError: - response = response.decode("latin1") - self._response_string = response - except: - response = response.decode("utf-8") - self._response_string = response - - if type(response) == dict: - self._response_hash = response - - - def as_string(self): - """ - Returns the response as a string - """ - return self._response_string - - - def as_hash(self): - """ - Returns the response as a hash - """ - if self._response_hash == None: - self._response_hash = apiconnector.util.response_to_hash(self._response_string) - return self._response_hash - - - def as_list_hash(self): - """ - Returns the response as a list hash - """ - if self._response_list_hash == None: - self._response_list_hash = apiconnector.util.response_to_list_hash(self.as_hash()) - return self._response_list_hash - - - def as_list(self): - """ - Returns the response as a list - """ - return self.as_list_hash()["ITEMS"] - - def __len__(self): - """ - Returns the number of items - """ - return self.as_list_hash()["COUNT"] - - def __getitem__(self, index): - """ - Returns the item for the given index - """ - if type(index) == int: - return self.as_list()[index] - if type(index) == str: - return self.as_hash()[index] - pass - - def code(self): - """ - Returns the response code - """ - return self.as_list_hash()["CODE"] - - def description(self): - """ - Returns the response description - """ - return self.as_list_hash()["DESCRIPTION"] - - def runtime(self): - """ - Returns the response runtime - """ - return self.as_list_hash()["RUNTIME"] - - def queuetime(self): - """ - Returns the response queuetime - """ - return self.as_list_hash()["QUEUETIME"] - - def properties(self): - """ - Returns the response properties - """ - return self.as_hash()["PROPERTY"] - - def property(self, index = None): - """ - Returns the property for a given index - If no index given, the complete property list is returned - """ - properties = self.properties() - if index: - try: - return properties[index] - except: - return None - else: - return properties - - def is_success(self): - """ - Returns true if the results is a success - Success = response code starting with 2 - """ - if str(self.code()).startswith("2"): - return True - else: - return False - - def is_tmp_error(self): - """ - Returns true if the results is a tmp error - tmp error = response code starting with 4 - """ - if str(self.code()).startswith("4"): - return True - else: - return False - - def columns(self): - """ - Returns the columns - """ - return self.as_list_hash()["COLUMNS"] - - def first(self): - """ - Returns the index of the first element - """ - return self.as_list_hash()["FIRST"] - - def last(self): - """ - Returns the index of the last element - """ - return self.as_list_hash()["LAST"] - - def count(self): - """ - Returns the number of list elements returned (= last - first + 1) - """ - return self.as_list_hash()["COUNT"] - - def limit(self): - """ - Returns the limit of the response - """ - return self.as_list_hash()["LIMIT"] - - def total(self): - """ - Returns the total number of elements found (!= count) - """ - return self.as_list_hash()["TOTAL"] - - def pages(self): - """ - Returns the number of pages - """ - return self.as_list_hash()["PAGES"] - - def page(self): - """ - Returns the number of the current page (starts with 1) - """ - return self.as_list_hash()["PAGE"] - - def prevpage(self): - """ - Returns the number of the previous page - - """ - try: - return self.as_list_hash()["PREVPAGE"] - except: - return None - - def prevpagefirst(self): - """ - Returns the first index for the previous page - """ - try: - return self.as_list_hash()["PREVPAGEFIRST"] - except: - return None - - def nextpage(self): - """ - Returns the number of the next page - """ - return self.as_list_hash()["NEXTPAGE"] - - def nextpagefirst(self): - """ - Returns the first index for the next page - """ - return self.as_list_hash()["NEXTPAGEFIRST"] - - def lastpagefirst(self): - """ - Returns the first index for the last page - """ - return self.as_list_hash()["LASTPAGEFIRST"] + def __init__(self, response): + """ + Constructor + """ + self._response_string = None + self._response_hash = None + self._response_list_hash = None + + # try/except to support old versions of python (python2.5) + try: + if isinstance(response, bytes): + response = response.decode("utf-8") + self._response_string = response + except UnicodeError: + response = response.decode("latin1") + self._response_string = response + except BaseException: + response = response.decode("utf-8") + self._response_string = response + + if isinstance(response, dict): + self._response_hash = response + + def as_string(self): + """ + Returns the response as a string + """ + return self._response_string + + def as_hash(self): + """ + Returns the response as a hash + """ + if self._response_hash is None: + self._response_hash = apiconnector.util.response_to_hash(self._response_string) + return self._response_hash + + def as_list_hash(self): + """ + Returns the response as a list hash + """ + if self._response_list_hash is None: + self._response_list_hash = apiconnector.util.response_to_list_hash(self.as_hash()) + return self._response_list_hash + + def as_list(self): + """ + Returns the response as a list + """ + return self.as_list_hash()["ITEMS"] + + def __len__(self): + """ + Returns the number of items + """ + return self.as_list_hash()["COUNT"] + + def __getitem__(self, index): + """ + Returns the item for the given index + """ + if isinstance(index, int): + return self.as_list()[index] + if isinstance(index, str): + return self.as_hash()[index] + pass + + def code(self): + """ + Returns the response code + """ + return self.as_list_hash()["CODE"] + + def description(self): + """ + Returns the response description + """ + return self.as_list_hash()["DESCRIPTION"] + + def runtime(self): + """ + Returns the response runtime + """ + return self.as_list_hash()["RUNTIME"] + + def queuetime(self): + """ + Returns the response queuetime + """ + return self.as_list_hash()["QUEUETIME"] + + def properties(self): + """ + Returns the response properties + """ + return self.as_hash()["PROPERTY"] + + def property(self, index=None): + """ + Returns the property for a given index + If no index given, the complete property list is returned + """ + properties = self.properties() + if index: + try: + return properties[index] + except BaseException: + return None + else: + return properties + + def is_success(self): + """ + Returns true if the results is a success + Success = response code starting with 2 + """ + if str(self.code()).startswith("2"): + return True + else: + return False + + def is_tmp_error(self): + """ + Returns true if the results is a tmp error + tmp error = response code starting with 4 + """ + if str(self.code()).startswith("4"): + return True + else: + return False + + def columns(self): + """ + Returns the columns + """ + return self.as_list_hash()["COLUMNS"] + + def first(self): + """ + Returns the index of the first element + """ + return self.as_list_hash()["FIRST"] + + def last(self): + """ + Returns the index of the last element + """ + return self.as_list_hash()["LAST"] + + def count(self): + """ + Returns the number of list elements returned (= last - first + 1) + """ + return self.as_list_hash()["COUNT"] + + def limit(self): + """ + Returns the limit of the response + """ + return self.as_list_hash()["LIMIT"] + + def total(self): + """ + Returns the total number of elements found (!= count) + """ + return self.as_list_hash()["TOTAL"] + + def pages(self): + """ + Returns the number of pages + """ + return self.as_list_hash()["PAGES"] + + def page(self): + """ + Returns the number of the current page (starts with 1) + """ + return self.as_list_hash()["PAGE"] + + def prevpage(self): + """ + Returns the number of the previous page + + """ + try: + return self.as_list_hash()["PREVPAGE"] + except BaseException: + return None + + def prevpagefirst(self): + """ + Returns the first index for the previous page + """ + try: + return self.as_list_hash()["PREVPAGEFIRST"] + except BaseException: + return None + + def nextpage(self): + """ + Returns the number of the next page + """ + return self.as_list_hash()["NEXTPAGE"] + + def nextpagefirst(self): + """ + Returns the first index for the next page + """ + return self.as_list_hash()["NEXTPAGEFIRST"] + + def lastpagefirst(self): + """ + Returns the first index for the last page + """ + return self.as_list_hash()["LASTPAGEFIRST"] diff --git a/hexonet/apiconnector/util.py b/hexonet/apiconnector/util.py index f8d3576..a50f010 100755 --- a/hexonet/apiconnector/util.py +++ b/hexonet/apiconnector/util.py @@ -2,178 +2,196 @@ from datetime import datetime import time try: - # For Python 3.0 and later - from urllib import parse as urlparse + # For Python 3.0 and later + from urllib import parse as urlparse except ImportError: - # Fall back to Python 2 - from urlparse import urlparse + # Fall back to Python 2 + from urlparse import urlparse import base64 def command_encode(command): - """ - Encode the command array in a command-string - """ - return "\n".join(_command_encode(command)) + """ + Encode the command array in a command-string + """ + return "\n".join(_command_encode(command)) + def _command_encode(command): - r = [] - - if type(command) == int: - command = str(command) - if type(command) == str: - return ["=" + command] - elif type(command) == dict: - for k,v in command.items(): - for v2 in _command_encode(v): - r.append(k.upper() + v2) - elif type(command) == list: - for (i, v) in enumerate(command): - for v2 in _command_encode(v): - r.append(str(i) + v2) - else: - pass - - return r + r = [] + + if isinstance(command, int): + command = str(command) + if isinstance(command, str): + return ["=" + command] + elif isinstance(command, dict): + for k, v in command.items(): + for v2 in _command_encode(v): + r.append(k.upper() + v2) + elif isinstance(command, list): + for (i, v) in enumerate(command): + for v2 in _command_encode(v): + r.append(str(i) + v2) + else: + pass + + return r def response_to_hash(response): - """ - Convert the response string as a hash - """ - r = {'PROPERTY':{}} - re1 = re.compile(r'^([^\=]*[^\t\= ])[\t ]*=[\t ]*(.*)') - re2 = re.compile(r'^property\[([^\]]*)\]', re.IGNORECASE) - for line in response.split("\n"): - m1 = re1.match(line) - if not m1: continue - attr = m1.group(1) - value = m1.group(2) - value = re.sub(r'[\t ]*$', '', value) - - m2 = re2.match(attr) - if m2: - prop = m2.group(1).upper() - prop = re.sub(r'\s', '', prop) - if prop not in r['PROPERTY']: - r['PROPERTY'][prop] = [] - r['PROPERTY'][prop].append(value) - else: - r[attr.upper()] = value - - if 'CODE' in r: - r['CODE'] = int(r['CODE']) - if 'RUNTIME' in r: - r['RUNTIME'] = float(r['RUNTIME']) - if 'QUEUETIME' in r: - r['QUEUETIME'] = float(r['QUEUETIME']) - return r - + """ + Convert the response string as a hash + """ + r = {'PROPERTY': {}} + re1 = re.compile(r'^([^\=]*[^\t\= ])[\t ]*=[\t ]*(.*)') + re2 = re.compile(r'^property\[([^\]]*)\]', re.IGNORECASE) + for line in response.split("\n"): + m1 = re1.match(line) + if not m1: + continue + attr = m1.group(1) + value = m1.group(2) + value = re.sub(r'[\t ]*$', '', value) + + m2 = re2.match(attr) + if m2: + prop = m2.group(1).upper() + prop = re.sub(r'\s', '', prop) + if prop not in r['PROPERTY']: + r['PROPERTY'][prop] = [] + r['PROPERTY'][prop].append(value) + else: + r[attr.upper()] = value + + if 'CODE' in r: + r['CODE'] = int(r['CODE']) + if 'RUNTIME' in r: + r['RUNTIME'] = float(r['RUNTIME']) + if 'QUEUETIME' in r: + r['QUEUETIME'] = float(r['QUEUETIME']) + return r def response_to_list_hash(response): - """ - Convert the response string as a list hash - """ - list_hash = { - 'CODE': "", - 'DESCRIPTION': "", - 'RUNTIME': "", - 'QUEUETIME': "", - 'ITEMS': [] - } - - if 'CODE' in response: list_hash['CODE'] = response['CODE'] - if 'DESCRIPTION' in response: list_hash['DESCRIPTION'] = response['DESCRIPTION'] - if 'RUNTIME' in response: list_hash['RUNTIME'] = response['RUNTIME'] - if 'QUEUETIME' in response: list_hash['QUEUETIME'] = response['QUEUETIME'] - - count = 0 - if 'PROPERTY' in response: - columns = None - if 'COLUMN' in response['PROPERTY']: - list_hash['COLUMNS'] = response['PROPERTY']['COLUMN'] - columns = {} - for col in list_hash['COLUMNS']: - columns[col] = 1 - else: - list_hash['COLUMNS'] = [] - - for prop,values in response['PROPERTY'].items(): - if prop == "COLUMN": continue - if prop in ['FIRST', 'LAST', 'LIMIT', 'COUNT', 'TOTAL']: - list_hash[prop] = int(response['PROPERTY'][prop][0]) - else: - if columns and not columns[prop]: continue - list_hash['COLUMNS'].append(prop) - index = 0 - for v in values: - if index >= len(list_hash['ITEMS']): - list_hash['ITEMS'].append({}) - list_hash['ITEMS'][index][prop] = v - index = index + 1 - if index > count: count = index - - if not 'COUNT' in list_hash: list_hash['COUNT'] = count - if not 'FIRST' in list_hash: list_hash['FIRST'] = 0 - if not 'TOTAL' in list_hash: list_hash['TOTAL'] = list_hash['COUNT'] - - if 'FIRST' in list_hash and 'LIMIT' in list_hash and list_hash['LIMIT'] > 0: - list_hash['PAGE'] = int(list_hash['FIRST'] / list_hash['LIMIT']) + 1 - if list_hash['PAGE'] > 1: - list_hash['PREVPAGE'] = list_hash['PAGE'] - 1 - list_hash['PREVPAGEFIRST'] = (list_hash['PREVPAGE'] - 1) * list_hash['LIMIT'] - list_hash['NEXTPAGE'] = list_hash['PAGE'] + 1 - list_hash['NEXTPAGEFIRST'] = (list_hash['NEXTPAGE'] - 1) * list_hash['LIMIT'] - - if 'TOTAL' in list_hash and 'LIMIT' in list_hash and list_hash['LIMIT'] > 0: - list_hash['PAGES'] = int(list_hash['TOTAL'] + list_hash['LIMIT'] - 1) / list_hash['LIMIT'] - list_hash['LASTPAGEFIRST'] = (list_hash['PAGES'] - 1) * list_hash['LIMIT'] - if 'NEXTPAGE' in list_hash and (list_hash['NEXTPAGE'] > list_hash['PAGES']): - list_hash['NEXTPAGE'] = None - list_hash['NEXTPAGEFIRST'] = None - - return list_hash - - -def sqltime(timestamp = None): - """ - Convert the Unix-Timestamp to a SQL datetime - If no timestamp given, returns the current datetime - """ - if timestamp: - return datetime.fromtimestamp(int(timestamp)).strftime('%Y-%m-%d %H:%M:%S') - else: - return datetime.now().strftime('%Y-%m-%d %H:%M:%S') + """ + Convert the response string as a list hash + """ + list_hash = { + 'CODE': "", + 'DESCRIPTION': "", + 'RUNTIME': "", + 'QUEUETIME': "", + 'ITEMS': [] + } + + if 'CODE' in response: + list_hash['CODE'] = response['CODE'] + if 'DESCRIPTION' in response: + list_hash['DESCRIPTION'] = response['DESCRIPTION'] + if 'RUNTIME' in response: + list_hash['RUNTIME'] = response['RUNTIME'] + if 'QUEUETIME' in response: + list_hash['QUEUETIME'] = response['QUEUETIME'] + + count = 0 + if 'PROPERTY' in response: + columns = None + if 'COLUMN' in response['PROPERTY']: + list_hash['COLUMNS'] = response['PROPERTY']['COLUMN'] + columns = {} + for col in list_hash['COLUMNS']: + columns[col] = 1 + else: + list_hash['COLUMNS'] = [] + + for prop, values in response['PROPERTY'].items(): + if prop == "COLUMN": + continue + if prop in ['FIRST', 'LAST', 'LIMIT', 'COUNT', 'TOTAL']: + list_hash[prop] = int(response['PROPERTY'][prop][0]) + else: + if columns and not columns[prop]: + continue + list_hash['COLUMNS'].append(prop) + index = 0 + for v in values: + if index >= len(list_hash['ITEMS']): + list_hash['ITEMS'].append({}) + list_hash['ITEMS'][index][prop] = v + index = index + 1 + if index > count: + count = index + + if 'COUNT' not in list_hash: + list_hash['COUNT'] = count + if 'FIRST' not in list_hash: + list_hash['FIRST'] = 0 + if 'TOTAL' not in list_hash: + list_hash['TOTAL'] = list_hash['COUNT'] + + if 'FIRST' in list_hash and 'LIMIT' in list_hash and list_hash['LIMIT'] > 0: + list_hash['PAGE'] = int(list_hash['FIRST'] / list_hash['LIMIT']) + 1 + if list_hash['PAGE'] > 1: + list_hash['PREVPAGE'] = list_hash['PAGE'] - 1 + list_hash['PREVPAGEFIRST'] = (list_hash['PREVPAGE'] - 1) * list_hash['LIMIT'] + list_hash['NEXTPAGE'] = list_hash['PAGE'] + 1 + list_hash['NEXTPAGEFIRST'] = (list_hash['NEXTPAGE'] - 1) * list_hash['LIMIT'] + + if 'TOTAL' in list_hash and 'LIMIT' in list_hash and list_hash['LIMIT'] > 0: + list_hash['PAGES'] = int(list_hash['TOTAL'] + list_hash['LIMIT'] - 1) / list_hash['LIMIT'] + list_hash['LASTPAGEFIRST'] = (list_hash['PAGES'] - 1) * list_hash['LIMIT'] + if 'NEXTPAGE' in list_hash and (list_hash['NEXTPAGE'] > list_hash['PAGES']): + list_hash['NEXTPAGE'] = None + list_hash['NEXTPAGEFIRST'] = None + + return list_hash + + +def sqltime(timestamp=None): + """ + Convert the Unix-Timestamp to a SQL datetime + If no timestamp given, returns the current datetime + """ + if timestamp: + return datetime.fromtimestamp(int(timestamp)).strftime('%Y-%m-%d %H:%M:%S') + else: + return datetime.now().strftime('%Y-%m-%d %H:%M:%S') + def timesql(sqldatetime): - """ - Convert the SQL datetime to Unix-Timestamp - """ - return int(time.mktime(datetime.strptime(sqldatetime, '%Y-%m-%d %H:%M:%S').timetuple())) + """ + Convert the SQL datetime to Unix-Timestamp + """ + return int(time.mktime(datetime.strptime(sqldatetime, '%Y-%m-%d %H:%M:%S').timetuple())) + def url_encode(string): - """ - URL-encodes string - This function is convenient when encoding a string to be used in a query part of a URL - """ - return urlparse.quote(string) + """ + URL-encodes string + This function is convenient when encoding a string to be used in a query + part of a URL + """ + return urlparse.quote(string) + def url_decode(string): - """ - Decodes URL-encoded string Decodes any %## encoding in the given string. - """ - return urlparse.unquote(string) + """ + Decodes URL-encoded string Decodes any %## encoding in the given string. + """ + return urlparse.unquote(string) + def base64_encode(string): - """ - Encodes data with MIME base64 - This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies. - """ - return base64.b64encode(string) + """ + Encodes data with MIME base64 + This encoding is designed to make binary data survive transport through transport layers that + are not 8-bit clean, such as mail bodies. + """ + return base64.b64encode(string) + def base64_decode(string): - """ - Decodes data encoded with MIME base64 - """ - return base64.b64decode(string) + """ + Decodes data encoded with MIME base64 + """ + return base64.b64decode(string) diff --git a/scripts/pep8check.sh b/scripts/pep8check.sh new file mode 100755 index 0000000..be1193f --- /dev/null +++ b/scripts/pep8check.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pep8 --first --show-source --show-pep8 diff --git a/scripts/pep8fix.sh b/scripts/pep8fix.sh new file mode 100755 index 0000000..39495ad --- /dev/null +++ b/scripts/pep8fix.sh @@ -0,0 +1,2 @@ +#!/bin/bash +autopep8 -i -a -a setup.py hexonet/apiconnector/__init__.py hexonet/apiconnector/connection.py hexonet/apiconnector/response.py hexonet/apiconnector/util.py diff --git a/setup.py b/setup.py index e9558ad..11153be 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ from setuptools import setup, find_packages + def read(*names, **kwargs): with io.open( os.path.join(os.path.dirname(__file__), *names), @@ -13,6 +14,7 @@ def read(*names, **kwargs): ) as fp: return fp.read() + def find_version(*file_paths): version_file = read(*file_paths) version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", @@ -21,6 +23,7 @@ def find_version(*file_paths): return version_match.group(1) raise RuntimeError("Unable to find version string.") + with open("README.md", "r") as fh: long_description = fh.read() @@ -46,10 +49,10 @@ def find_version(*file_paths): scripts=[], zip_safe=True, classifiers=( - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent" + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent" ), - namespace_packages = ['hexonet'] - ) \ No newline at end of file + namespace_packages=['hexonet'] + )