lswapi 0.4.3__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
lswapi-0.5.2/PKG-INFO ADDED
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.3
2
+ Name: lswapi
3
+ Version: 0.5.2
4
+ Summary: a python client library for easy leaseweb api access
5
+ License: Apache-2.0
6
+ Author: Nico Di Rocco
7
+ Author-email: n.dirocco@global.leaseweb.com
8
+ Requires-Python: >= 3.9
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
+ Classifier: Operating System :: Unix
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Utilities
20
+ Project-URL: Homepage, http://developer.leaseweb.com
21
+ Project-URL: Issues, https://github.com/nrocco/lswapi
22
+ Description-Content-Type: text/markdown
23
+
24
+ # lswapi (beta)
25
+
26
+ [![Actions Status](https://github.com/nrocco/lswapi/workflows/Python%20package/badge.svg)](https://github.com/nrocco/lswapi/actions)
27
+
28
+ Python module to talk to Leaseweb's API.
29
+
30
+ For more information refer to the documentation available at
31
+ [http://developer.leaseweb.com]
32
+
33
+ This module contains two api clients:
34
+
35
+ 1. One is based on the `requests` module.
36
+ 2. The second one is based on the `aiohttp` module for asyncio support.
37
+
38
+
39
+ ## Installation
40
+
41
+ Install the module using pip. This will not install `requests` or `aiohttp`.
42
+
43
+ pip install lswapi
44
+
45
+
46
+ You can install optional depencies, such as `aiohttp`:
47
+
48
+ pip install 'lswapi[aio]'
49
+
50
+ Or if you prefer to use `requests`:
51
+
52
+ pip install 'lswapi[requests]'
53
+
54
+
55
+ ## Usage
56
+
57
+
58
+ ### Using requests
59
+
60
+ The `lswapi.requests.get_leaseweb_api` function creates an instance of the Leaseweb Api
61
+ object with the `X-Lsw-Auth` key. You can provide the api key as an argument
62
+ to `get_leaseweb_api`
63
+
64
+ $ python
65
+ >>> from lswapi.requests import get_leaseweb_api
66
+ >>> client = get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
67
+ >>> response = client.get("/bareMetals/v2/servers")
68
+ >>> servers = response.json()
69
+
70
+
71
+ or get `LSW_API_KEY` from an environment variable:
72
+
73
+ $ LSW_API_KEY=xxxx-xxxx-xxxxx python
74
+ >>> from lswapi.requests import get_leaseweb_api
75
+ >>> client = get_leaseweb_api()
76
+ >>> response = client.get("/bareMetals/v2/servers")
77
+ >>> servers = response.json()
78
+
79
+
80
+ ### Using aiohttp
81
+
82
+ The `lswapi.aio.get_leaseweb_api` function creates an instance of the Leaseweb Api
83
+ object with the `X-Lsw-Auth` key. You can provide the api key as an argument
84
+ to `get_leaseweb_api` or via the environment variable `LSW_API_KEY`:
85
+
86
+ $ python -m asyncio
87
+ >>> from lswapi.aio import get_leaseweb_api
88
+ >>> client = get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
89
+ >>> response = await client.get("/bareMetals/v2/servers")
90
+ >>> servers = await response.json()
91
+
92
+
93
+ Contribute
94
+ ----------
95
+
96
+ 1. Fork it
97
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
98
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
99
+ 4. Make sure that tests pass (`make test`)
100
+ 5. Push to the branch (`git push origin my-new-feature`)
101
+ 6. Create new Pull Request
102
+
lswapi-0.5.2/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # lswapi (beta)
2
+
3
+ [![Actions Status](https://github.com/nrocco/lswapi/workflows/Python%20package/badge.svg)](https://github.com/nrocco/lswapi/actions)
4
+
5
+ Python module to talk to Leaseweb's API.
6
+
7
+ For more information refer to the documentation available at
8
+ [http://developer.leaseweb.com]
9
+
10
+ This module contains two api clients:
11
+
12
+ 1. One is based on the `requests` module.
13
+ 2. The second one is based on the `aiohttp` module for asyncio support.
14
+
15
+
16
+ ## Installation
17
+
18
+ Install the module using pip. This will not install `requests` or `aiohttp`.
19
+
20
+ pip install lswapi
21
+
22
+
23
+ You can install optional depencies, such as `aiohttp`:
24
+
25
+ pip install 'lswapi[aio]'
26
+
27
+ Or if you prefer to use `requests`:
28
+
29
+ pip install 'lswapi[requests]'
30
+
31
+
32
+ ## Usage
33
+
34
+
35
+ ### Using requests
36
+
37
+ The `lswapi.requests.get_leaseweb_api` function creates an instance of the Leaseweb Api
38
+ object with the `X-Lsw-Auth` key. You can provide the api key as an argument
39
+ to `get_leaseweb_api`
40
+
41
+ $ python
42
+ >>> from lswapi.requests import get_leaseweb_api
43
+ >>> client = get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
44
+ >>> response = client.get("/bareMetals/v2/servers")
45
+ >>> servers = response.json()
46
+
47
+
48
+ or get `LSW_API_KEY` from an environment variable:
49
+
50
+ $ LSW_API_KEY=xxxx-xxxx-xxxxx python
51
+ >>> from lswapi.requests import get_leaseweb_api
52
+ >>> client = get_leaseweb_api()
53
+ >>> response = client.get("/bareMetals/v2/servers")
54
+ >>> servers = response.json()
55
+
56
+
57
+ ### Using aiohttp
58
+
59
+ The `lswapi.aio.get_leaseweb_api` function creates an instance of the Leaseweb Api
60
+ object with the `X-Lsw-Auth` key. You can provide the api key as an argument
61
+ to `get_leaseweb_api` or via the environment variable `LSW_API_KEY`:
62
+
63
+ $ python -m asyncio
64
+ >>> from lswapi.aio import get_leaseweb_api
65
+ >>> client = get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
66
+ >>> response = await client.get("/bareMetals/v2/servers")
67
+ >>> servers = await response.json()
68
+
69
+
70
+ Contribute
71
+ ----------
72
+
73
+ 1. Fork it
74
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
75
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
76
+ 4. Make sure that tests pass (`make test`)
77
+ 5. Push to the branch (`git push origin my-new-feature`)
78
+ 6. Create new Pull Request
@@ -0,0 +1,63 @@
1
+ [project]
2
+ name = "lswapi"
3
+ version = "0.5.2"
4
+ description = "a python client library for easy leaseweb api access"
5
+ authors = [
6
+ {name = "Nico Di Rocco",email = "n.dirocco@global.leaseweb.com"}
7
+ ]
8
+ classifiers = [
9
+ "Development Status :: 5 - Production/Stable",
10
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
11
+ "Operating System :: Unix",
12
+ "Programming Language :: Python",
13
+ "Programming Language :: Python :: 3.9",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Software Development :: Libraries :: Python Modules",
19
+ "Topic :: Utilities"
20
+ ]
21
+ license = "Apache-2.0"
22
+ readme = "README.md"
23
+ requires-python = ">= 3.9"
24
+ dependencies = [
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "http://developer.leaseweb.com"
29
+ Issues = "https://github.com/nrocco/lswapi"
30
+
31
+
32
+ [project.entry-points."httpie.plugins.auth.v1"]
33
+ httpie_lswapi = "lswapi.httpie:ApiAuthPlugin"
34
+
35
+
36
+ [build-system]
37
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
38
+ build-backend = "poetry.core.masonry.api"
39
+
40
+
41
+ [tool.poetry.group.dev.dependencies]
42
+ flake8 = "^7.3.0"
43
+ pytest = "^8.4.1"
44
+ pytest-cov = "^6.2.1"
45
+ requests-mock = "^1.12.1"
46
+
47
+
48
+ [tool.poetry.group.httpie.dependencies]
49
+ httpie = "^3.2.4"
50
+
51
+
52
+ [tool.poetry.group.requests.dependencies]
53
+ requests = "^2.32.4"
54
+
55
+
56
+ [tool.poetry.group.aio.dependencies]
57
+ aiodns = "^3.5.0"
58
+ aiohttp = "^3.12.15"
59
+
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
63
+
@@ -0,0 +1,2 @@
1
+ __auth_token_url__ = "https://auth.leaseweb.com/token"
2
+ __api_base_url__ = "https://api.leaseweb.com"
@@ -0,0 +1,27 @@
1
+ from lswapi import __api_base_url__
2
+ from lswapi import __auth_token_url__
3
+ from lswapi.aio.client import LeasewebHttpClient
4
+ from lswapi.aio.middleware import LoggingMiddleware
5
+ from lswapi.aio.oauth import AccessTokenFileStore
6
+ from lswapi.aio.oauth import LeasewebOAuthMiddleware
7
+ from os import environ
8
+
9
+
10
+ def get_leaseweb_api(api_key=None, client_id=None, client_secret=None, base_url=None, token_url=None, token_store=None):
11
+ base_url = base_url or environ.get("LSW_BASE_URL", __api_base_url__)
12
+ token_url = token_url or environ.get("LSW_AUTH_URL", __auth_token_url__)
13
+ token_store = token_store or environ.get("LSW_AUTH_TOKEN_STORE")
14
+ api_key = api_key or environ.get("LSW_API_KEY")
15
+ if api_key:
16
+ return LeasewebHttpClient(base_url, middlewares=[LoggingMiddleware(debug=False)], headers={"X-Lsw-Auth": api_key})
17
+ if not client_id or not client_secret:
18
+ raise Exception("No authentication method specified")
19
+ return LeasewebHttpClient(base_url, middlewares=[
20
+ LeasewebOAuthMiddleware(
21
+ client_id,
22
+ client_secret,
23
+ token_url,
24
+ store=AccessTokenFileStore(token_store) if token_store else None,
25
+ ),
26
+ LoggingMiddleware(debug=False),
27
+ ])
@@ -0,0 +1,50 @@
1
+ from aiohttp import ClientSession
2
+
3
+
4
+ class LeasewebHttpClient:
5
+ def __init__(self, *args, middlewares: list[callable] = [], **kwargs):
6
+ self.middlewares = middlewares
7
+ self.__create_session = lambda: ClientSession(*args, **kwargs)
8
+ self.session = None
9
+
10
+ async def _run_middlewares(self, method, url, next_func, **kwargs):
11
+ async def middleware_chain(index, method, url, **kwargs):
12
+ if index < len(self.middlewares):
13
+ return await self.middlewares[index](
14
+ method, url, lambda m, u, **k: middleware_chain(index + 1, m, u, **k), **kwargs
15
+ )
16
+ return await next_func(method, url, **kwargs)
17
+ return await middleware_chain(0, method, url, **kwargs)
18
+
19
+ async def _request(self, method, url, **kwargs):
20
+ if not self.session:
21
+ self.session = self.__create_session()
22
+ return await self.session.request(method, url, **kwargs)
23
+
24
+ async def request(self, method, url, **kwargs):
25
+ return await self._run_middlewares(method, url, self._request, **kwargs)
26
+
27
+ async def get(self, url, **kwargs):
28
+ return await self.request("GET", url, **kwargs)
29
+
30
+ async def post(self, url, **kwargs):
31
+ return await self.request("POST", url, **kwargs)
32
+
33
+ async def put(self, url, **kwargs):
34
+ return await self.request("PUT", url, **kwargs)
35
+
36
+ async def patch(self, url, **kwargs):
37
+ return await self.request("PATCH", url, **kwargs)
38
+
39
+ async def delete(self, url, **kwargs):
40
+ return await self.request("DELETE", url, **kwargs)
41
+
42
+ async def close(self):
43
+ if self.session:
44
+ await self.session.close()
45
+
46
+ async def __aenter__(self):
47
+ return self
48
+
49
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
50
+ await self.close()
@@ -0,0 +1,20 @@
1
+ import time
2
+ import logging
3
+
4
+
5
+ class LoggingMiddleware:
6
+ def __init__(self, debug=False) -> None:
7
+ self.debug = debug
8
+
9
+ async def __call__(self, method, url, next_func, **kwargs):
10
+ start = time.monotonic()
11
+ response = await next_func(method, url, **kwargs)
12
+ end = time.monotonic()
13
+ logging.info(f"Request to {response.method} {response.url} took {(end - start):.3f} seconds and resulted in a {response.status} {response.reason}")
14
+ if self.debug:
15
+ for header, value in response.request_info.headers.items():
16
+ logging.debug(f">>> {header}: {value}")
17
+ logging.debug(f"<<< HTTP/{response.version.major}.{response.version.minor} {response.status} {response.reason}")
18
+ for header, value in response.headers.items():
19
+ logging.debug(f"<<< {header}: {value}")
20
+ return response
@@ -0,0 +1,85 @@
1
+ import aiohttp
2
+ import asyncio
3
+ import json
4
+ import os
5
+ import time
6
+
7
+ from lswapi.aio.client import LeasewebHttpClient
8
+ from lswapi.aio.middleware import LoggingMiddleware
9
+
10
+
11
+ class AccessTokenInMemoryStore:
12
+ def __init__(self):
13
+ self.token = None
14
+
15
+ async def load(self):
16
+ return self.token
17
+
18
+ async def save(self, token):
19
+ self.token = token
20
+
21
+ async def remove(self):
22
+ self.token = None
23
+
24
+
25
+ class AccessTokenFileStore:
26
+ def __init__(self, filepath):
27
+ self.token = None
28
+ self.filepath = filepath
29
+ self.lock = asyncio.Lock()
30
+
31
+ async def load(self):
32
+ async with self.lock:
33
+ if self.token:
34
+ return self.token
35
+ if not os.path.exists(self.filepath):
36
+ return None
37
+ with open(self.filepath, "r") as file:
38
+ try:
39
+ self.token = json.load(file)
40
+ except json.decoder.JSONDecodeError:
41
+ os.remove(self.filepath)
42
+ return self.token
43
+
44
+ async def save(self, token):
45
+ async with self.lock:
46
+ with open(self.filepath, "w") as file:
47
+ json.dump(token, file)
48
+ self.token = token
49
+
50
+ async def remove(self):
51
+ async with self.lock:
52
+ if os.path.exists(self.filepath):
53
+ os.remove(self.filepath)
54
+ self.token = None
55
+
56
+
57
+ class LeasewebOAuthMiddleware:
58
+ def __init__(self, client_id, client_secret, token_url, store=None):
59
+ self.client_id = client_id
60
+ self.client_secret = client_secret
61
+ self.token_url = token_url
62
+ self.store = store or AccessTokenInMemoryStore()
63
+ self.lock = asyncio.Lock()
64
+
65
+ async def __call__(self, method, url, next_func, **kwargs):
66
+ async with self.lock:
67
+ token = await self.store.load()
68
+ if not token or token.get("expires_at") < time.time():
69
+ token = await self.__fetch_access_token()
70
+ await self.store.save(token)
71
+ if "headers" not in kwargs:
72
+ kwargs["headers"] = {}
73
+ kwargs["headers"]["Authorization"] = "{token_type} {access_token}".format(**token)
74
+ return await next_func(method, url, **kwargs)
75
+
76
+ async def __fetch_access_token(self):
77
+ auth = aiohttp.BasicAuth(login=self.client_id, password=self.client_secret)
78
+ async with LeasewebHttpClient(auth=auth, middlewares=[LoggingMiddleware(debug=False)]) as client:
79
+ payload = {"grant_type": "client_credentials"}
80
+ response = await client.post(self.token_url, data=payload)
81
+ assert response.status == 200
82
+ token = await response.json()
83
+ token["issued_at"] = int(time.time())
84
+ token["expires_at"] = token["issued_at"] + token["expires_in"] - 10
85
+ return token
@@ -1,14 +1,15 @@
1
1
  """
2
2
  LswApi auth plugin for HTTPie.
3
3
  """
4
+ from httpie.plugins import AuthPlugin
4
5
  from json import loads, dumps
5
- from time import time
6
+ from lswapi import __auth_token_url__
7
+ from lswapi.requests import fetch_access_token
6
8
  from os import path
7
- from lswapi import __auth_token_url__, fetch_access_token
8
- from httpie.plugins import AuthPlugin
9
+ from time import time
9
10
 
10
11
 
11
- __token_store__ = path.expanduser('~/.lswapi.token')
12
+ __token_store__ = path.expanduser("~/.lswapi.token")
12
13
 
13
14
 
14
15
  class LswApiAuth(object):
@@ -18,25 +19,25 @@ class LswApiAuth(object):
18
19
 
19
20
  def __call__(self, r):
20
21
  if path.exists(__token_store__):
21
- with open(__token_store__, 'r') as file:
22
+ with open(__token_store__, "r") as file:
22
23
  token = loads(file.read())
23
- if 'expires_at' in token and token['expires_at'] > time():
24
- r.headers['Authorization'] = '{token_type} {access_token}'.format(**token)
24
+ if "expires_at" in token and token["expires_at"] > time():
25
+ r.headers["Authorization"] = "{token_type} {access_token}".format(**token)
25
26
  return r
26
27
 
27
28
  token = fetch_access_token(__auth_token_url__, self.client_id, self.client_secret)
28
29
 
29
- with open(__token_store__, 'w') as file:
30
+ with open(__token_store__, "w") as file:
30
31
  file.write(dumps(token))
31
32
 
32
- r.headers['Authorization'] = '{token_type} {access_token}'.format(**token)
33
+ r.headers["Authorization"] = "{token_type} {access_token}".format(**token)
33
34
  return r
34
35
 
35
36
 
36
37
  class ApiAuthPlugin(AuthPlugin):
37
- name = 'LswApi Oauth'
38
- auth_type = 'lswapi'
39
- description = 'LeaseWeb Api Oauth Authentication'
38
+ name = "LswApi Oauth"
39
+ auth_type = "lswapi"
40
+ description = "Leaseweb Api Oauth Authentication"
40
41
 
41
42
  def get_auth(self, username, password):
42
43
  return LswApiAuth(username, password)
@@ -0,0 +1,21 @@
1
+ from lswapi import __api_base_url__
2
+ from lswapi import __auth_token_url__
3
+ from lswapi.requests.session import LeasewebSession
4
+ from lswapi.requests.session import LeasewebApiKeyAuth
5
+ from os import environ
6
+
7
+
8
+ def get_leaseweb_api(api_key=None, client_id=None, client_secret=None, base_url=None, token_url=None, token_store=None):
9
+ base_url = base_url or environ.get("LSW_BASE_URL", __api_base_url__)
10
+ token_url = token_url or environ.get("LSW_AUTH_URL", __auth_token_url__)
11
+ token_store = token_store or environ.get("LSW_AUTH_TOKEN_STORE", None)
12
+ api_key = api_key or environ.get("LSW_API_KEY")
13
+ if api_key:
14
+ api = LeasewebSession(base_url=base_url)
15
+ api.auth = (LeasewebApiKeyAuth(api_key))
16
+ return api
17
+ client_id = client_id or environ.get("LSW_CLIENT_ID")
18
+ client_secret = client_secret or environ.get("LSW_CLIENT_SECRET")
19
+ if client_id and client_secret:
20
+ return LeasewebSession(base_url=base_url, client_id=client_id, client_secret=client_secret, token_url=token_url, token_store=token_store)
21
+ raise Exception("No authentication method specified")
@@ -0,0 +1,12 @@
1
+ from requests import post
2
+ from time import time
3
+
4
+
5
+ def fetch_access_token(token_url, client_id, client_secret):
6
+ response = post(token_url, auth=(client_id, client_secret), data={"grant_type": "client_credentials"})
7
+ if response.status_code != 200:
8
+ raise Exception("Could not obtain an access token")
9
+ token = response.json()
10
+ token["created_at"] = int(time())
11
+ token["expires_at"] = token["created_at"] + token["expires_in"] - 10
12
+ return token
@@ -0,0 +1,49 @@
1
+ from json import load, dump
2
+ from lswapi import __api_base_url__
3
+ from lswapi import __auth_token_url__
4
+ from lswapi.requests.oauth import fetch_access_token
5
+ from os import path
6
+ from requests import Session
7
+ from requests.auth import AuthBase
8
+ from time import time
9
+
10
+
11
+ class LeasewebApiKeyAuth(AuthBase):
12
+ def __init__(self, lsw_auth_key):
13
+ self.lsw_auth_key = lsw_auth_key
14
+
15
+ def __call__(self, r):
16
+ r.headers["X-Lsw-Auth"] = self.lsw_auth_key
17
+ return r
18
+
19
+
20
+ class LeasewebSession(Session):
21
+ access_token = None
22
+
23
+ def __init__(self, client_id=None, client_secret=None, base_url=None, token_url=None, token_store=None):
24
+ self.base_url = base_url or __api_base_url__
25
+ self.token_url = token_url or __auth_token_url__
26
+ self.token_store = token_store
27
+ self.client_id = client_id
28
+ self.client_secret = client_secret
29
+ super().__init__()
30
+
31
+ def _fetch_access_token(self):
32
+ if not self.access_token and self.token_store:
33
+ if path.exists(self.token_store):
34
+ with open(self.token_store, "r") as file:
35
+ self.access_token = load(file)
36
+ if self.access_token and self.access_token.get("expires_at") > time():
37
+ return self.access_token
38
+ self.access_token = fetch_access_token(self.token_url, self.client_id, self.client_secret)
39
+ if self.token_store:
40
+ with open(self.token_store, "w") as file:
41
+ dump(self.access_token, file)
42
+ return self.access_token
43
+
44
+ def request(self, method, url, data=None, headers={}, **kwargs):
45
+ if self.client_id and self.client_secret:
46
+ headers["Authorization"] = "{token_type} {access_token}".format(**self._fetch_access_token())
47
+ if not url.startswith("http"):
48
+ url = "{}/{}".format(self.base_url, url.lstrip("/"))
49
+ return super().request(method, url, headers=headers, data=data, **kwargs)
lswapi-0.4.3/MANIFEST.in DELETED
@@ -1,6 +0,0 @@
1
- include LICENSE.txt
2
- include README.md
3
- include requirements.txt
4
- recursive-exclude * __pycache__
5
- recursive-exclude * *.py[co]
6
- recursive-exclude tests *
lswapi-0.4.3/PKG-INFO DELETED
@@ -1,75 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: lswapi
3
- Version: 0.4.3
4
- Summary: a python client library for easy leaseweb api access
5
- Home-page: http://developer.leaseweb.com
6
- Download-URL: https://github.com/nrocco/lswapi/tags
7
- Author: Nico Di Rocco
8
- Author-email: n.dirocco@global.leaseweb.com
9
- License: GPLv3
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
12
- Classifier: Operating System :: Unix
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 2
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.7
17
- Classifier: Programming Language :: Python :: 3.8
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Classifier: Topic :: Utilities
23
- License-File: LICENSE.txt
24
-
25
- lswapi (beta)
26
- =============
27
-
28
- [![Actions Status](https://github.com/nrocco/lswapi/workflows/Python%20package/badge.svg)](https://github.com/nrocco/lswapi/actions)
29
-
30
- Python module to talk to LeaseWeb's API.
31
-
32
- For more information refer to the documentation available at
33
- [http://developer.leaseweb.com]
34
-
35
-
36
- Installation
37
- ------------
38
-
39
- Install the module using pip
40
-
41
- pip install lswapi
42
-
43
-
44
- Usage
45
- -----
46
-
47
- The `lswapi.get_leaseweb_api` function creates an instance of the LeaseWeb Api
48
- object with the `X-Lsw-Auth` key. You can provide the api key as an argument
49
- to `get_leaseweb_api`
50
-
51
- $ python
52
- >>> import lswapi
53
- >>> client = lswapi.get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
54
- >>> response = client.get("/bareMetals/v2/servers")
55
- >>> servers = response.json()
56
-
57
-
58
- or as an environment variable `LSW_API_KEY`
59
-
60
- $ LSW_API_KEY=xxxx-xxxx-xxxxx python
61
- >>> import lswapi
62
- >>> client = lswapi.get_leaseweb_api()
63
- >>> response = client.get("/bareMetals/v2/servers")
64
- >>> servers = response.json()
65
-
66
-
67
- Contribute
68
- ----------
69
-
70
- 1. Fork it
71
- 2. Create your feature branch (`git checkout -b my-new-feature`)
72
- 3. Commit your changes (`git commit -am 'Add some feature'`)
73
- 4. Make sure that tests pass (`make test`)
74
- 5. Push to the branch (`git push origin my-new-feature`)
75
- 6. Create new Pull Request
lswapi-0.4.3/README.md DELETED
@@ -1,51 +0,0 @@
1
- lswapi (beta)
2
- =============
3
-
4
- [![Actions Status](https://github.com/nrocco/lswapi/workflows/Python%20package/badge.svg)](https://github.com/nrocco/lswapi/actions)
5
-
6
- Python module to talk to LeaseWeb's API.
7
-
8
- For more information refer to the documentation available at
9
- [http://developer.leaseweb.com]
10
-
11
-
12
- Installation
13
- ------------
14
-
15
- Install the module using pip
16
-
17
- pip install lswapi
18
-
19
-
20
- Usage
21
- -----
22
-
23
- The `lswapi.get_leaseweb_api` function creates an instance of the LeaseWeb Api
24
- object with the `X-Lsw-Auth` key. You can provide the api key as an argument
25
- to `get_leaseweb_api`
26
-
27
- $ python
28
- >>> import lswapi
29
- >>> client = lswapi.get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
30
- >>> response = client.get("/bareMetals/v2/servers")
31
- >>> servers = response.json()
32
-
33
-
34
- or as an environment variable `LSW_API_KEY`
35
-
36
- $ LSW_API_KEY=xxxx-xxxx-xxxxx python
37
- >>> import lswapi
38
- >>> client = lswapi.get_leaseweb_api()
39
- >>> response = client.get("/bareMetals/v2/servers")
40
- >>> servers = response.json()
41
-
42
-
43
- Contribute
44
- ----------
45
-
46
- 1. Fork it
47
- 2. Create your feature branch (`git checkout -b my-new-feature`)
48
- 3. Commit your changes (`git commit -am 'Add some feature'`)
49
- 4. Make sure that tests pass (`make test`)
50
- 5. Push to the branch (`git push origin my-new-feature`)
51
- 6. Create new Pull Request
@@ -1,81 +0,0 @@
1
- from json import dump as json_dump
2
- from json import load as json_load
3
- from os import environ, path
4
- from requests.auth import AuthBase
5
- from requests import Session
6
- from requests import post
7
- from time import time
8
-
9
- __version__ = '0.4.3'
10
- __auth_token_url__ = 'https://auth.leaseweb.com/token'
11
- __api_base_url__ = 'https://api.leaseweb.com'
12
-
13
-
14
- def get_leaseweb_api(api_key=None, client_id=None, client_secret=None, base_url=None, token_url=None, token_store=None):
15
- base_url = base_url or environ.get('LSW_BASE_URL', __api_base_url__)
16
- token_url = token_url or environ.get('LSW_AUTH_URL', __auth_token_url__)
17
- token_store = token_store or environ.get('LSW_AUTH_TOKEN_STORE', None)
18
-
19
- api_key = api_key or environ.get('LSW_API_KEY')
20
- if api_key:
21
- api = LeaseWebSession(base_url=base_url)
22
- api.auth = (LeasewebApiKeyAuth(api_key))
23
- return api
24
-
25
- client_id = client_id or environ.get('LSW_CLIENT_ID')
26
- client_secret = client_secret or environ.get('LSW_CLIENT_SECRET')
27
- if client_id and client_secret:
28
- return LeaseWebSession(base_url=base_url, client_id=client_id, client_secret=client_secret, token_url=token_url, token_store=token_store)
29
-
30
- raise Exception("No authentication method specified")
31
-
32
-
33
- def fetch_access_token(token_url, client_id, client_secret):
34
- response = post(token_url, auth=(client_id, client_secret), data={'grant_type': 'client_credentials'})
35
- if response.status_code != 200:
36
- raise Exception('Could not obtain an access token')
37
- token = response.json()
38
- token['created_at'] = int(time())
39
- token['expires_at'] = token['created_at'] + token['expires_in'] - 10
40
- return token
41
-
42
-
43
- class LeasewebApiKeyAuth(AuthBase):
44
- def __init__(self, lsw_auth_key):
45
- self.lsw_auth_key = lsw_auth_key
46
-
47
- def __call__(self, r):
48
- r.headers['X-Lsw-Auth'] = self.lsw_auth_key
49
- return r
50
-
51
-
52
- class LeaseWebSession(Session):
53
- access_token = None
54
-
55
- def __init__(self, client_id=None, client_secret=None, base_url=None, token_url=None, token_store=None):
56
- self.base_url = base_url or __api_base_url__
57
- self.token_url = token_url or __auth_token_url__
58
- self.token_store = token_store
59
- self.client_id = client_id
60
- self.client_secret = client_secret
61
- super(LeaseWebSession, self).__init__()
62
-
63
- def _fetch_access_token(self):
64
- if not self.access_token and self.token_store:
65
- if path.exists(self.token_store):
66
- with open(self.token_store, 'r') as file:
67
- self.access_token = json_load(file)
68
- if self.access_token and self.access_token.get('expires_at') > time():
69
- return self.access_token
70
- self.access_token = fetch_access_token(self.token_url, self.client_id, self.client_secret)
71
- if self.token_store:
72
- with open(self.token_store, 'w') as file:
73
- json_dump(self.access_token, file)
74
- return self.access_token
75
-
76
- def request(self, method, url, data=None, headers={}, **kwargs):
77
- if self.client_id and self.client_secret:
78
- headers['Authorization'] = '{token_type} {access_token}'.format(**self._fetch_access_token())
79
- if not url.startswith('http'):
80
- url = '{}/{}'.format(self.base_url, url.lstrip('/'))
81
- return super(LeaseWebSession, self).request(method, url, headers=headers, data=data, **kwargs)
@@ -1,75 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: lswapi
3
- Version: 0.4.3
4
- Summary: a python client library for easy leaseweb api access
5
- Home-page: http://developer.leaseweb.com
6
- Download-URL: https://github.com/nrocco/lswapi/tags
7
- Author: Nico Di Rocco
8
- Author-email: n.dirocco@global.leaseweb.com
9
- License: GPLv3
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
12
- Classifier: Operating System :: Unix
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 2
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.7
17
- Classifier: Programming Language :: Python :: 3.8
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Classifier: Topic :: Utilities
23
- License-File: LICENSE.txt
24
-
25
- lswapi (beta)
26
- =============
27
-
28
- [![Actions Status](https://github.com/nrocco/lswapi/workflows/Python%20package/badge.svg)](https://github.com/nrocco/lswapi/actions)
29
-
30
- Python module to talk to LeaseWeb's API.
31
-
32
- For more information refer to the documentation available at
33
- [http://developer.leaseweb.com]
34
-
35
-
36
- Installation
37
- ------------
38
-
39
- Install the module using pip
40
-
41
- pip install lswapi
42
-
43
-
44
- Usage
45
- -----
46
-
47
- The `lswapi.get_leaseweb_api` function creates an instance of the LeaseWeb Api
48
- object with the `X-Lsw-Auth` key. You can provide the api key as an argument
49
- to `get_leaseweb_api`
50
-
51
- $ python
52
- >>> import lswapi
53
- >>> client = lswapi.get_leaseweb_api(api_key="xxxx-xxx-xxxxxx")
54
- >>> response = client.get("/bareMetals/v2/servers")
55
- >>> servers = response.json()
56
-
57
-
58
- or as an environment variable `LSW_API_KEY`
59
-
60
- $ LSW_API_KEY=xxxx-xxxx-xxxxx python
61
- >>> import lswapi
62
- >>> client = lswapi.get_leaseweb_api()
63
- >>> response = client.get("/bareMetals/v2/servers")
64
- >>> servers = response.json()
65
-
66
-
67
- Contribute
68
- ----------
69
-
70
- 1. Fork it
71
- 2. Create your feature branch (`git checkout -b my-new-feature`)
72
- 3. Commit your changes (`git commit -am 'Add some feature'`)
73
- 4. Make sure that tests pass (`make test`)
74
- 5. Push to the branch (`git push origin my-new-feature`)
75
- 6. Create new Pull Request
@@ -1,14 +0,0 @@
1
- LICENSE.txt
2
- MANIFEST.in
3
- README.md
4
- requirements.txt
5
- setup.cfg
6
- setup.py
7
- lswapi/__init__.py
8
- lswapi.egg-info/PKG-INFO
9
- lswapi.egg-info/SOURCES.txt
10
- lswapi.egg-info/dependency_links.txt
11
- lswapi.egg-info/entry_points.txt
12
- lswapi.egg-info/requires.txt
13
- lswapi.egg-info/top_level.txt
14
- lswapi/httpie/__init__.py
@@ -1,2 +0,0 @@
1
- [httpie.plugins.auth.v1]
2
- httpie_lswapi = lswapi.httpie:ApiAuthPlugin
@@ -1 +0,0 @@
1
- requests
@@ -1 +0,0 @@
1
- lswapi
@@ -1 +0,0 @@
1
- requests
lswapi-0.4.3/setup.cfg DELETED
@@ -1,24 +0,0 @@
1
- [bumpversion]
2
- current_version = 0.4.3
3
- commit = True
4
- tag = True
5
-
6
- [wheel]
7
- universal = 1
8
-
9
- [flake8]
10
- exclude = .git,__pycache__,build,dist,env
11
- max-complexity = 10
12
- max-line-length = 1000
13
-
14
- [pycodestyle]
15
- ignore = E501
16
-
17
- [bumpversion:file:setup.py]
18
-
19
- [bumpversion:file:lswapi/__init__.py]
20
-
21
- [egg_info]
22
- tag_build =
23
- tag_date = 0
24
-
lswapi-0.4.3/setup.py DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env python
2
- import io
3
- import codecs
4
-
5
- from setuptools import setup, find_packages
6
-
7
-
8
- def load_requirements(filename):
9
- with io.open(filename, encoding='utf-8') as reqfile:
10
- return [line.strip() for line in reqfile if not line.startswith('#')]
11
-
12
-
13
- setup(
14
- name='lswapi',
15
- description='a python client library for easy leaseweb api access',
16
- version='0.4.3',
17
- author='Nico Di Rocco',
18
- author_email='n.dirocco@global.leaseweb.com',
19
- url='http://developer.leaseweb.com',
20
- license='GPLv3',
21
- long_description=codecs.open('README.md', 'rb', 'utf-8').read(),
22
- download_url='https://github.com/nrocco/lswapi/tags',
23
- include_package_data=True,
24
- install_requires=load_requirements('requirements.txt'),
25
- tests_require=[
26
- 'httpie',
27
- 'coverage',
28
- ],
29
- entry_points={
30
- 'httpie.plugins.auth.v1': [
31
- 'httpie_lswapi = lswapi.httpie:ApiAuthPlugin'
32
- ]
33
- },
34
- packages=find_packages(exclude=['tests']),
35
- test_suite='tests',
36
- classifiers=[
37
- 'Development Status :: 5 - Production/Stable',
38
- 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
39
- 'Operating System :: Unix',
40
- 'Programming Language :: Python',
41
- 'Programming Language :: Python :: 2',
42
- 'Programming Language :: Python :: 3',
43
- 'Programming Language :: Python :: 3.7',
44
- 'Programming Language :: Python :: 3.8',
45
- 'Programming Language :: Python :: 3.9',
46
- 'Programming Language :: Python :: 3.10',
47
- 'Programming Language :: Python :: 3.11',
48
- 'Topic :: Software Development :: Libraries :: Python Modules',
49
- 'Topic :: Utilities'
50
- ],
51
- )
File without changes