[DEV] add better support of isort, black and base on injection for connection that permit test

This commit is contained in:
Edouard DUPIN 2023-02-06 23:22:27 +01:00
parent 6c63ecccf9
commit f95621f6bb
14 changed files with 483 additions and 199 deletions

View File

@ -0,0 +1,16 @@
[flake8]
# Temporary, should be fixed and reenabled
# B006 Do not use mutable data structures for argument defaults. They are created during function definition time. All calls to the function reuse this one instance of that data structure, persisting changes between them.
# B028 'state_name' is manually surrounded by quotes, consider using the `!r` conversion flag.
# B902 blind except Exception
# Permanently disabled, because conflicting with other rules
# B950 line too long (conflicting with black)
# E203 whitespace before ':' (conflicting with black)
# E501 line too long (81 > 79 characters) (conflicting with black)
# W503 line break before binary operator: Nothing to be done on this one, we use W504 instead
ignore = B006, B028, B902, B950, E203, E501, W503, ANN101, ANN102, ANN401
max-line-length = 99
# max-complexity = 18
select = A,ANN,B,C,D,E,F,I,W,T

View File

@ -0,0 +1,18 @@
# Configuration settings for isort.
[settings]
py_version=38
profile=black
line_length = 80
lines_after_imports = 2
known_firstparty=nfar_*
sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
order_by_type = false
combine_as_imports = true
force_grid_wrap = 3
force_sort_within_sections = true
include_trailing_comma = true
skip = setup.py
use_parentheses = true

View File

@ -1,13 +1,20 @@
#!/bin/python3
# Importing the library
import psutil
import argparse
import time
import subprocess
import json
from pathlib import Path
import subprocess
import time
from typing import Dict, List
from karanage import KaranageState, KaranageConnection, KaranageException, StateSystem
from karanage import (
KaranageConnection,
KaranageException,
KaranageState,
StateSystem,
)
import psutil
cpu_core_count = psutil.cpu_count(logical=False)
cpu_thread_count = psutil.cpu_count()
@ -122,12 +129,12 @@ if __name__ == '__main__':
# Load arguments:
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--config", type=str, default="/etc/karanage/system.json", help="json configuration file")
parser.add_argument("-C", "--connection", type=str, default=None, help="json configuration file")
parser.add_argument("-C", "--connection", type=str, help="json configuration file")
# This element are read from the connection file:
parser.add_argument("-u", "--url", type=str, default=None, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, default=None, help="Group the the message")
parser.add_argument("-T", "--token", type=str, default=None, help="Token to access to the server")
parser.add_argument("-u", "--url", type=str, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, help="Group the the message")
parser.add_argument("-T", "--token", type=str, help="Token to access to the server")
# This element are read from the configuration file:
parser.add_argument("-t", "--topic", type=str, default="PC/system", help="Topic of the message")

View File

@ -1,26 +1,31 @@
#!/bin/python3
# Importing the library
import psutil
import argparse
import time
import subprocess
import json
from pathlib import Path
import subprocess
import time
from typing import Dict, List
from karanage import KaranageException, KaranageConnection, KaranageState
from karanage import (
KaranageConnection,
KaranageException,
KaranageState,
)
import psutil
if __name__ == '__main__':
# Load arguments:
parser = argparse.ArgumentParser()
parser.add_argument("-C", "--connection", type=str, default=None, help="json configuration file")
parser.add_argument("-t", "--topic", type=str, default=None, help="Topic of the message")
parser.add_argument("-s", "--since", type=str, default=None, help="Iso date since the value time must be")
parser.add_argument("-C", "--connection", type=str, help="json configuration file")
parser.add_argument("-t", "--topic", type=str, help="Topic of the message")
parser.add_argument("-s", "--since", type=str, help="Iso date since the value time must be")
# This element are read from the connection file:
parser.add_argument("-u", "--url", type=str, default=None, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, default=None, help="Group the the message")
parser.add_argument("-T", "--token", type=str, default=None, help="Token to access to the server")
parser.add_argument("-u", "--url", type=str, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, help="Group the the message")
parser.add_argument("-T", "--token", type=str, help="Token to access to the server")
args = parser.parse_args()

View File

@ -1,27 +1,29 @@
#!/bin/python3
# Importing the library
import psutil
import argparse
import time
import subprocess
import json
from pathlib import Path
import subprocess
import time
from typing import Dict, List
from karanage import KaranageConnection, KaranageState, KaranageState
from karanage import KaranageConnection, KaranageState
import psutil
if __name__ == '__main__':
# Load arguments:
parser = argparse.ArgumentParser()
parser.add_argument("-C", "--connection", type=str, default=None, help="json configuration file")
parser.add_argument("-t", "--topic", type=str, default=None, help="Topic of the message")
parser.add_argument("-s", "--since", type=str, default=None, help="Iso date since the value time must be")
parser.add_argument("-S", "--since-id", type=str, default=None, help="Remote BDD id to start request")
parser.add_argument("-C", "--connection", type=str, help="json configuration file")
parser.add_argument("-t", "--topic", type=str, help="Topic of the message")
parser.add_argument("-s", "--since", type=str, help="Iso date since the value time must be")
parser.add_argument("-S", "--since-id", type=str, help="Remote BDD id to start request")
parser.add_argument("-l", "--limit", type=int, default=100, help="Limit the number of request")
# This element are read from the connection file:
parser.add_argument("-u", "--url", type=str, default=None, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, default=None, help="Group the the message")
parser.add_argument("-T", "--token", type=str, default=None, help="Token to access to the server")
parser.add_argument("-u", "--url", type=str, help="Base URL of the web service")
parser.add_argument("-g", "--group", type=str, help="Group the the message")
parser.add_argument("-T", "--token", type=str, help="Token to access to the server")
args = parser.parse_args()

View File

@ -11,51 +11,53 @@
from setuptools import setup
import os
def readme():
with open('README.md') as f:
return f.read()
with open("README.md") as f:
return f.read()
def read_version_file():
if not os.path.isfile("version.txt"):
return ""
file = open("version.txt", "r")
data_file = file.read()
file.close()
if len(data_file) > 4 and data_file[-4:] == "-dev":
data_file = data_file[:-4]
return data_file
if not os.path.isfile("version.txt"):
return ""
file = open("version.txt", "r")
data_file = file.read()
file.close()
if len(data_file) > 4 and data_file[-4:] == "-dev":
data_file = data_file[:-4]
return data_file
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
setup(name='karanage-tools',
version=read_version_file(),
description='Karanage generic tools',
long_description=readme(),
url='https://gitea.atria-soft.org/kangaroo-and-rabbit/karanage',
author='Edouard DUPIN',
author_email='yui.heero@gmail.com',
license='MPL-2',
packages=['karanage-tools'],
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
'Programming Language :: Python',
'Operating System :: POSIX',
'Topic :: Software Development :: Libraries'
],
install_requires=[
'karanage=='+read_version_file()
],
long_description_content_type="text/markdown",
keywords='system cpu status',
scripts=[
'bin/karanage-system',
'bin/karanage-tools-state-get',
'bin/karanage-tools-state-history-get',
],
include_package_data = True,
zip_safe=False)
setup(
name="karanage-tools",
version=read_version_file(),
description="Karanage generic tools",
long_description=readme(),
url="https://gitea.atria-soft.org/kangaroo-and-rabbit/karanage",
author="Edouard DUPIN",
author_email="yui.heero@gmail.com",
license="MPL-2",
packages=["karanage-tools"],
classifiers=[
"Development Status :: 4 - Beta",
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
"Programming Language :: Python",
"Operating System :: POSIX",
"Topic :: Software Development :: Libraries",
],
install_requires=["karanage==" + read_version_file()],
long_description_content_type="text/markdown",
keywords="system cpu status",
scripts=[
"bin/karanage-system",
"bin/karanage-tools-state-get",
"bin/karanage-tools-state-history-get",
],
include_package_data=True,
zip_safe=False,
)
#To developp: sudo ./setup.py install
# To developp: sudo ./setup.py install
# sudo ./setup.py develop
#TO register all in pip: ./setup.py register sdist upload
# TO register all in pip: ./setup.py register sdist upload

View File

@ -0,0 +1,16 @@
[flake8]
# Temporary, should be fixed and reenabled
# B006 Do not use mutable data structures for argument defaults. They are created during function definition time. All calls to the function reuse this one instance of that data structure, persisting changes between them.
# B028 'state_name' is manually surrounded by quotes, consider using the `!r` conversion flag.
# B902 blind except Exception
# Permanently disabled, because conflicting with other rules
# B950 line too long (conflicting with black)
# E203 whitespace before ':' (conflicting with black)
# E501 line too long (81 > 79 characters) (conflicting with black)
# W503 line break before binary operator: Nothing to be done on this one, we use W504 instead
ignore = B006, B028, B902, B950, E203, E501, W503, ANN101, ANN102, ANN401
max-line-length = 99
# max-complexity = 18
select = A,ANN,B,C,D,E,F,I,W,T

View File

@ -0,0 +1,18 @@
# Configuration settings for isort.
[settings]
py_version=38
profile=black
line_length = 80
lines_after_imports = 2
known_firstparty=nfar_*
sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
order_by_type = false
combine_as_imports = true
force_grid_wrap = 3
force_sort_within_sections = true
include_trailing_comma = true
skip = setup.py
use_parentheses = true

View File

@ -7,8 +7,12 @@
##
## @license MPL v2.0 (see license file)
##
from .connection import (
KaranageConnection,
KaranageConnectionInterface,
KaranageMock,
KaranageResponse,
)
from .exception import KaranageException
from .connection import KaranageConnection
from .state import StateSystem, KaranageState
from .log import KaranageLog, GroupLogElement
from .log import GroupLogElement, KaranageLog
from .state import KaranageState, StateSystem

View File

@ -7,21 +7,88 @@
##
## @license MPL v2.0 (see license file)
##
from abc import ABC, abstractmethod
import copy
import enum
import requests
import json
from typing import Dict, Optional
from pathlib import Path
from typing import (
Dict,
List,
NamedTuple,
Optional,
)
import requests
class KaranageConnection:
def __init__(self,
url: Optional[str] = None,
group: Optional[str] = None,
token: Optional[str] = None,
config_file: Optional[str] = None,
default_values: Optional[str] = None) -> None:
""" Initialize the communication class.
class KaranageResponse:
def __init__(
self, url: str, status: Optional[int] = None, data: Optional[str] = None
):
self.url = url
self.status = status
self.data = data
class KaranageConnectionInterface(ABC):
"""Generic connection interface to access to karanage interface.
:param ABC: Abstraction model class.
"""
@abstractmethod
def post(
self,
service: str,
url_offset: str,
data: Optional[Dict] = None,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
"""POST request on the server.
:param service: Service on which we need to access.
:param url_offset: Offset of the url server.
:param data: Json data to post, defaults to None.
:param headers: Headers value to add on the request, defaults to None.
:param params: Parameters to send on the server, defaults to None.
:return: Result of the request.
"""
@abstractmethod
def get(
self,
service: str,
url_offset: str,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
"""GET request on the server.
:param service: Service on which we need to access.
:param url_offset: Offset of the url server.
:param headers: Headers value to add on the request, defaults to None.
:param params: Parameters to send on the server, defaults to None.
:return: Result of the request.
"""
class KaranageConnection(KaranageConnectionInterface):
"""Connection on the karanage REST server.
:param KaranageConnectionInterface: Model of connection.
"""
def __init__(
self,
url: Optional[str] = None,
group: Optional[str] = None,
token: Optional[str] = None,
config_file: Optional[str] = None,
default_values: Optional[str] = None,
) -> None:
"""Initialize the communication class.
:param url: URL of the karanage API server.
:param group: Group of the message (token need to have the autorotation to published on it).
:param token: Token to validate the access on the application.
@ -40,7 +107,7 @@ class KaranageConnection:
if "token" in default_values:
self.token = default_values["token"]
# keep correct config file:
if config_file is None:
if config_file is None:
config_file = "/etc/karanage/connection.json"
# check if the config exist:
if Path(config_file).exists():
@ -64,11 +131,124 @@ class KaranageConnection:
if token is not None:
self.token = token
def get_url(self, service: str):
return f"{self.url}/{service}/{self.group}"
def get_url(self, service: str, url_offset: Optional[str]):
"""Get the formatted URL for specific service and specific offset
def get_header(self):
header = {}
if self.token is not None and len(self.token) >15:
header['Authorization'] = f"zota {self.token}"
return header
:param service: Name of the service we want to connect on.
:param url_offset: additional url path.
:return: the specific url string (all before ?).
"""
if url_offset is None:
return f"{self.url}/{service}/{self.group}"
return f"{self.url}/{service}/{self.group}/{url_offset}"
def update_header(self, headers):
"""Add security header on the client header config.
:param headers: _description_
:return: _description_
"""
if headers is None:
headers = {}
else:
headers = copy.deepcopy(headers)
if self.token is not None and len(self.token) > 15:
headers["Authorization"] = f"zota {self.token}"
return headers
# @override
def post(
self,
service: str,
url_offset: str,
data: Optional[Dict] = None,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
headers = self.update_header(headers)
url = self.get_url(service, url_offset)
ret = requests.post(url, json=data, headers=headers, params=params)
try:
return KaranageResponse(url, ret.status_code, ret.content.decode("utf-8"))
except requests.exceptions.ConnectionError as ex:
raise KaranageException(f"Fail connect server: '{url}'", 0, str(ex))
# @override
def get(
self,
service: str,
url_offset: str,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
headers = self.update_header(headers)
url = self.get_url(service, url_offset)
ret = requests.get(url, headers=headers, params=params)
try:
return KaranageResponse(url, ret.status_code, ret.content.decode("utf-8"))
except requests.exceptions.ConnectionError as ex:
raise KaranageException(f"Fail connect server: '{url}'", 0, str(ex))
class MockData(NamedTuple):
"""Received Mock data from the karanage backend.
:param NamedTuple: Tuple generic interface
"""
type: str
service: str
url_offset: str
data: Dict
headers: Dict
params: Dict
class KaranageMock(KaranageConnectionInterface):
"""Simple Karanage Mock to permit to abstract
Note: This class is for test only !!!
:param KaranageConnectionInterface: Model of connection.
"""
def __init__(
self,
) -> None:
"""Initialize the communication class."""
self.request: List[MockData] = []
def post(
self,
service: str,
url_offset: str,
data: Optional[Dict] = None,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
self.request.append(
MockData("POST", service, url_offset, data, headers, params)
)
return KaranageResponse(f"{service}/{url_offset}", 200, "{}")
def get(
self,
service: str,
url_offset: str,
headers: Optional[Dict] = None,
params: Optional[Dict] = None,
) -> KaranageResponse:
self.request.append(MockData("GET", service, url_offset, None, headers, params))
return KaranageResponse(f"{service}/{url_offset}", 200, "{}")
def get_values(self) -> List[KaranageResponse]:
"""get the list of last added values
:returns: all collected values.
"""
out = self.request
self.request = []
return out
def clear_values(self) -> None:
"""Clear all the received data."""
self.request = []

View File

@ -8,14 +8,15 @@
## @license MPL v2.0 (see license file)
##
class KaranageException(Exception):
def __init__(self, message, error_id, error_message):
def __init__(self, message, error_id, error_message):
# Call the base class constructor with the parameters it needs
super().__init__(message)
# Now for your custom code...
self.error_id = error_id
self.error_message = error_message
def __str__(self):
return f"{Exception.__str__(self)} Status={self.error_id} message='{self.error_message}'"

View File

@ -7,23 +7,33 @@
##
## @license MPL v2.0 (see license file)
##
import enum
import requests
import json
from datetime import datetime, timezone
from typing import Dict, Optional, List
from .connection import KaranageConnection
import enum
import json
from typing import (
Dict,
List,
Optional,
)
import requests
from .connection import KaranageConnectionInterface
from .exception import KaranageException
class GroupLogElement:
def __init__(self, id: int, data: str, time: datetime = None):
self.id = id
self.time = time
self.data = data
## Generic karanage sending system.
class KaranageLog:
def __init__(self, connection: KaranageConnection, system: Optional[str] = None) -> None:
def __init__(
self, connection: KaranageConnectionInterface, system: Optional[str] = None
) -> None:
"""Initialize the communication class.
:param connection: Connection interface.
"""
@ -31,12 +41,13 @@ class KaranageLog:
self.system = system
self.service = "log"
def get_url(self):
if self.system is None:
return self.connection.get_url(self.service)
return f"{self.connection.get_url(self.service)}/{self.system}"
def send(self, data: Dict, id: Optional[int] = None, uuid_group: Optional[int] = None, time: Optional[datetime] = None) -> None:
def send(
self,
data: Dict,
id: Optional[int] = None,
uuid_group: Optional[int] = None,
time: Optional[datetime] = None,
) -> None:
"""Send a message to the server.
:param data: Data to send to the server
:param id: Local internal ID
@ -50,36 +61,36 @@ class KaranageLog:
param["uuid"] = uuid_group
if time is not None:
param["time"] = time.astimezone(timezone.utc).isoformat()
header = self.connection.get_header()
try:
ret = requests.post(self.get_url(), json=data, headers=header, params=param)
except requests.exceptions.ConnectionError as ex:
raise KaranageException(f"Fail connect server: {self.get_url()}", 0, str(ex))
if not 200 <= ret.status_code <= 299:
raise KaranageException(f"Fail send message: {self.get_url()}", ret.status_code, ret.content.decode("utf-8"))
ret = self.connection.post(self.service, self.system, data=data, params=param)
if not 200 <= ret.status <= 299:
raise KaranageException(
f"Fail send message: '{ret.url}'", ret.status, ret.data
)
def send_multiple(self, data_input: List[GroupLogElement], uuid_group: Optional[int]= None) -> None:
def send_multiple(
self, data_input: List[GroupLogElement], uuid_group: Optional[int] = None
) -> None:
"""Send multiple log message to the server.
:param data: Data to send to the server
:param uuid_group: local internal group UUID
"""
# Convert:
data = []
for elem in data_input:
data.append({
"id": elem.id,
"time": elem.time.astimezone(timezone.utc).isoformat(),
"data": elem.data,
})
data.append(
{
"id": elem.id,
"time": elem.time.astimezone(timezone.utc).isoformat(),
"data": elem.data,
}
)
param = {}
if uuid_group is not None:
param["uuid"] = uuid_group
header = self.connection.get_header()
try:
ret = requests.post(f"{self.get_url()}/push_multiple", json=data, headers=header, params=param)
except requests.exceptions.ConnectionError as ex:
raise KaranageException(f"Fail connect server: {self.get_url()}", 0, str(ex))
if not 200 <= ret.status_code <= 299:
raise KaranageException(f"Fail send message: {self.get_url()}", ret.status_code, ret.content.decode("utf-8"))
ret = self.connection.post(
self.service, f"{self.system}/push_multiple", data=data, params=param
)
if not 200 <= ret.status <= 299:
raise KaranageException(
f"Fail send message: '{ret.url}'", ret.status, ret.data
)

View File

@ -8,31 +8,35 @@
## @license MPL v2.0 (see license file)
##
import enum
import requests
import json
from typing import Dict, Optional
from .connection import KaranageConnection
import requests
from .connection import KaranageConnectionInterface
from .exception import KaranageException
class StateSystem(enum.Enum):
OK = "OK"
FAIL = "FAIL"
DOWN = "DOWN"
## Generic karanage sending system.
class KaranageState:
def __init__(self, connection: KaranageConnection) -> None:
def __init__(self, connection: KaranageConnectionInterface) -> None:
"""Initialize the communication class.
:param connection: Connection interface.
"""
self.connection = connection
def get_url(self, service: str, topic: Optional[str] = None):
if topic is None:
return self.connection.get_url(service)
return f"{self.connection.get_url(service)}/{topic}"
def send(self, topic: str, data: Optional[Dict] = None, state: StateSystem = StateSystem.OK) -> None:
def send(
self,
topic: str,
data: Optional[Dict] = None,
state: StateSystem = StateSystem.OK,
) -> None:
"""Send a message to the server.
:param topic: Topic where to publish the data.
:param data: Data to send to the server
@ -43,48 +47,46 @@ class KaranageState:
param = {}
if state is not None:
param["state"] = state.value
header = self.connection.get_header()
try:
ret = requests.post(self.get_url("state", topic), json=data, headers=header, params=param)
except requests.exceptions.ConnectionError as ex:
raise KaranageException(f"Fail connect server: {self.get_url('state', topic)}", 0, str(ex))
if not 200 <= ret.status_code <= 299:
raise KaranageException(f"Fail send message: {self.get_url('state', topic)}", ret.status_code, ret.content.decode("utf-8"))
ret = self.connection.post("state", topic, data=data, params=param)
if not 200 <= ret.status <= 299:
raise KaranageException(
f"Fail send message: '{ret.url}'", ret.status, ret.data
)
def gets(self, topic: Optional[str] = None, since: Optional[str] = None) -> Dict:
"""Get all the topic fom the server.
:param since: ISO1866 time value.
:return: A dictionary with the requested data.
"""
param = { }
header = self.connection.get_header()
param = {}
if since is not None:
param["since"] = since
ret = requests.get(self.get_url("state", topic), headers=header, params=param)
#print(ret.content.decode('utf-8'))
if 200 <= ret.status_code <= 299:
return json.loads(ret.content.decode('utf-8'))
raise KaranageException(f"Fail get data: {self.get_url('state', topic)}", ret.status_code, ret.content.decode("utf-8"))
ret = self.connection.get("state", topic, params=param)
if 200 <= ret.status <= 299:
return json.loads(ret.data)
raise KaranageException(f"Fail get data: '{ret.url}'", ret.status, ret.data)
def get_history(self, topic: Optional[str] = None, since: Optional[str] = None, since_id: Optional[int] = None, limit: Optional[int] = None) -> Dict:
def get_history(
self,
topic: Optional[str] = None,
since: Optional[str] = None,
since_id: Optional[int] = None,
limit: Optional[int] = None,
) -> Dict:
"""Get all the topic fom the server.
:param since: ISO1866 time value.
:param since_id: remote BDD index of the field.
:param limit: the number of value we want to get
:return: A dictionary with the requested data.
"""
param = { }
header = self.connection.get_header()
param = {}
if since is not None:
param["since"] = since
if since_id is not None:
param["sinceId"] = since_id
if limit is not None:
param["limit"] = limit
ret = requests.get(self.get_url("state_history", topic), headers=header, params=param)
#print(ret.content.decode('utf-8'))
if 200 <= ret.status_code <= 299:
return json.loads(ret.content.decode('utf-8'))
raise KaranageException(f"Fail get data: {self.get_url('state_history', topic)}", ret.status_code, ret.content.decode("utf-8"))
ret = self.connection.get("state_history", topic, params=param)
if 200 <= ret.status <= 299:
return json.loads(ret.data)
raise KaranageException(f"Fail get data: '{ret.url}'", ret.status, ret.data)

View File

@ -11,50 +11,52 @@
from setuptools import setup
import os
def readme():
with open('README.md') as f:
return f.read()
with open("README.md") as f:
return f.read()
def read_version_file():
if not os.path.isfile("version.txt"):
return ""
file = open("version.txt", "r")
data_file = file.read()
file.close()
if len(data_file) > 4 and data_file[-4:] == "-dev":
data_file = data_file[:-4]
return data_file
if not os.path.isfile("version.txt"):
return ""
file = open("version.txt", "r")
data_file = file.read()
file.close()
if len(data_file) > 4 and data_file[-4:] == "-dev":
data_file = data_file[:-4]
return data_file
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
setup(name='karanage',
version=read_version_file(),
description='Karanage interface is a simple interface to access to the karanage service to send and receive data',
long_description=readme(),
url='https://gitea.atria-soft.org/kangaroo-and-rabbit/karanage',
author='Edouard DUPIN',
author_email='yui.heero@gmail.com',
license='MPL-2',
packages=['karanage'],
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
'Programming Language :: Python',
'Operating System :: POSIX',
'Topic :: Software Development :: Libraries'
],
install_requires=[
'requests'
],
long_description_content_type="text/markdown",
keywords='kar karanage',
include_package_data = True,
zip_safe=False)
setup(
name="karanage",
version=read_version_file(),
description="Karanage interface is a simple interface to access to the karanage service to send and receive data",
long_description=readme(),
url="https://gitea.atria-soft.org/kangaroo-and-rabbit/karanage",
author="Edouard DUPIN",
author_email="yui.heero@gmail.com",
license="MPL-2",
packages=["karanage"],
classifiers=[
"Development Status :: 4 - Beta",
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
"Programming Language :: Python",
"Operating System :: POSIX",
"Topic :: Software Development :: Libraries",
],
install_requires=["requests"],
long_description_content_type="text/markdown",
keywords="kar karanage",
include_package_data=True,
zip_safe=False,
)
#To developp: sudo ./setup.py install --user
# To developp: sudo ./setup.py install --user
# sudo ./setup.py develop --user
#TO register all in pip: ./setup.py register sdist upload
# TO register all in pip: ./setup.py register sdist upload
# https://packaging.python.org/en/latest/tutorials/packaging-projects/
# python3 -m build
# python3 -m twine upload dist/*