pyixapi 0.2.1__tar.gz → 0.2.3__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.
Files changed (42) hide show
  1. {pyixapi-0.2.1/pyixapi.egg-info → pyixapi-0.2.3}/PKG-INFO +9 -9
  2. {pyixapi-0.2.1 → pyixapi-0.2.3}/README.md +0 -2
  3. pyixapi-0.2.3/pyixapi/__init__.py +5 -0
  4. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/api.py +1 -1
  5. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/endpoint.py +3 -1
  6. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/query.py +8 -2
  7. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/token.py +26 -18
  8. pyixapi-0.2.3/pyproject.toml +78 -0
  9. pyixapi-0.2.1/.github/FUNDING.yml +0 -4
  10. pyixapi-0.2.1/.github/dependabot.yml +0 -19
  11. pyixapi-0.2.1/.github/workflows/publish.yml +0 -29
  12. pyixapi-0.2.1/.github/workflows/tests.yml +0 -26
  13. pyixapi-0.2.1/.gitignore +0 -102
  14. pyixapi-0.2.1/PKG-INFO +0 -79
  15. pyixapi-0.2.1/docs/Makefile +0 -17
  16. pyixapi-0.2.1/docs/advanced.rst +0 -74
  17. pyixapi-0.2.1/docs/conf.py +0 -158
  18. pyixapi-0.2.1/docs/endpoint.rst +0 -5
  19. pyixapi-0.2.1/docs/index.rst +0 -29
  20. pyixapi-0.2.1/docs/request.rst +0 -8
  21. pyixapi-0.2.1/docs/response.rst +0 -8
  22. pyixapi-0.2.1/pyixapi/__init__.py +0 -11
  23. pyixapi-0.2.1/pyixapi.egg-info/SOURCES.txt +0 -38
  24. pyixapi-0.2.1/pyixapi.egg-info/dependency_links.txt +0 -1
  25. pyixapi-0.2.1/pyixapi.egg-info/not-zip-safe +0 -1
  26. pyixapi-0.2.1/pyixapi.egg-info/requires.txt +0 -2
  27. pyixapi-0.2.1/pyixapi.egg-info/top_level.txt +0 -1
  28. pyixapi-0.2.1/pyproject.toml +0 -8
  29. pyixapi-0.2.1/requirements-dev.txt +0 -2
  30. pyixapi-0.2.1/requirements.txt +0 -2
  31. pyixapi-0.2.1/setup.cfg +0 -4
  32. pyixapi-0.2.1/setup.py +0 -33
  33. pyixapi-0.2.1/tests/__init__.py +0 -0
  34. pyixapi-0.2.1/tests/fixtures/api/authenticate.json +0 -4
  35. pyixapi-0.2.1/tests/fixtures/api/refresh_authentication.json +0 -4
  36. pyixapi-0.2.1/tests/test_api.py +0 -86
  37. pyixapi-0.2.1/tests/util.py +0 -15
  38. {pyixapi-0.2.1 → pyixapi-0.2.3}/LICENSE +0 -0
  39. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/__init__.py +0 -0
  40. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/response.py +0 -0
  41. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/core/util.py +0 -0
  42. {pyixapi-0.2.1 → pyixapi-0.2.3}/pyixapi/models.py +0 -0
@@ -1,21 +1,22 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyixapi
3
- Version: 0.2.1
4
- Summary: IX-API client library
5
- Home-page: https://github.com/peering-manager/pyixapi
3
+ Version: 0.2.3
4
+ Summary: Python API client library for IX-API
5
+ License: Apache-2.0
6
6
  Author: Guillaume Mazoyer
7
7
  Author-email: oss@mazoyer.eu
8
- License: Apache2
9
- Keywords: ix-api,internet-exchange,peering
8
+ Requires-Python: >=3.8,<4.0
10
9
  Classifier: Intended Audience :: Developers
11
- Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: License :: OSI Approved :: Apache Software License
12
11
  Classifier: Programming Language :: Python :: 3
13
12
  Classifier: Programming Language :: Python :: 3.8
14
13
  Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Dist: PyJWT (>=2.4.0,<2.9)
18
+ Requires-Dist: requests (>=2.20.0,<3.0)
17
19
  Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
20
 
20
21
  # pyixapi
21
22
 
@@ -30,8 +31,6 @@ Supported versions are:
30
31
 
31
32
  To install run `pip install pyixapi`.
32
33
 
33
- Alternatively, you can clone the repo and run `python setup.py install`.
34
-
35
34
  ## Quick Start
36
35
 
37
36
  To begin, import pyixapi and instantiate the API.
@@ -77,3 +76,4 @@ DXDB:PAS:00008
77
76
  ```
78
77
 
79
78
  Write queries are not implemented yet.
79
+
@@ -11,8 +11,6 @@ Supported versions are:
11
11
 
12
12
  To install run `pip install pyixapi`.
13
13
 
14
- Alternatively, you can clone the repo and run `python setup.py install`.
15
-
16
14
  ## Quick Start
17
15
 
18
16
  To begin, import pyixapi and instantiate the API.
@@ -0,0 +1,5 @@
1
+ from .core.api import API as api
2
+ from .core.api import __version__ # noqa: F401
3
+ from .core.query import ContentError, RequestError
4
+
5
+ __all__ = ("api", "ContentError", "RequestError")
@@ -29,7 +29,7 @@ from pyixapi.models import (
29
29
  RoleAssignment,
30
30
  )
31
31
 
32
- __version__ = "0.2.1"
32
+ __version__ = "0.2.2"
33
33
 
34
34
 
35
35
  class API(object):
@@ -62,7 +62,9 @@ class Endpoint(object):
62
62
  try:
63
63
  next(response)
64
64
  raise ValueError(
65
- "get() returned more than one result. Check that the kwarg(s) passed are valid for this endpoint or use filter() or all() instead."
65
+ "get() returned more than one result. Check that the kwarg(s) "
66
+ "passed are valid for this endpoint or use filter() or all() "
67
+ "instead."
66
68
  )
67
69
  except StopIteration:
68
70
  return value
@@ -19,9 +19,15 @@ class RequestError(Exception):
19
19
  )
20
20
  else:
21
21
  try:
22
- self.message = f"The request failed with code {r.status_code} {r.reason}: {r.json()}"
22
+ self.message = (
23
+ f"The request failed with code {r.status_code} "
24
+ f"{r.reason}: {r.json()}"
25
+ )
23
26
  except ValueError:
24
- self.message = f"The request failed with code {r.status_code} {r.reason} but details were not found as JSON."
27
+ self.message = (
28
+ f"The request failed with code {r.status_code} "
29
+ f"{r.reason} but details were not found as JSON."
30
+ )
25
31
 
26
32
  super(RequestError, self).__init__(r)
27
33
  self.req = r
@@ -1,4 +1,5 @@
1
- from datetime import datetime
1
+ import warnings
2
+ from datetime import datetime, timezone
2
3
 
3
4
  import jwt
4
5
 
@@ -11,7 +12,7 @@ class InvalidTokenException(Exception):
11
12
  pass
12
13
 
13
14
 
14
- class Token(object):
15
+ class Token:
15
16
  """
16
17
  A token is at the core of the authentication mechanism of IX-API.
17
18
 
@@ -24,37 +25,43 @@ class Token(object):
24
25
  continue using the API.
25
26
  """
26
27
 
27
- def __init__(self, token, issued_at, expires_at):
28
- self.encoded = token # Cache signed token data
29
- self.issued_at = issued_at
30
- self.expires_at = expires_at
28
+ def __init__(self, token: str, expires_at: datetime) -> None:
29
+ self.encoded: str = token # Cache signed token data
30
+ self.expires_at: datetime = expires_at
31
31
 
32
- def __str__(self):
32
+ def __str__(self) -> str:
33
33
  return self.encoded
34
34
 
35
- def __repr__(self):
36
- return f"<Token issued_at={self.issued_at} ttl={self.ttl}s>"
35
+ def __repr__(self) -> str:
36
+ return f"<Token ttl={self.ttl}s>"
37
37
 
38
38
  @property
39
- def ttl(self):
39
+ def issued_at(self) -> datetime:
40
+ warnings.warn(
41
+ "Property 'issued_at' is deprecated and value will always be set to now.",
42
+ DeprecationWarning,
43
+ )
44
+ return datetime.now(tz=timezone.utc)
45
+
46
+ @property
47
+ def ttl(self) -> int:
40
48
  """
41
49
  TTL is the number of seconds, from now, before the token expires.
42
50
  """
43
- seconds = (self.expires_at - datetime.now()).total_seconds()
51
+ seconds = (self.expires_at - datetime.now(timezone.utc)).total_seconds()
44
52
  return max(0, seconds)
45
53
 
46
54
  @property
47
- def is_expired(self):
55
+ def is_expired(self) -> bool:
48
56
  """
49
57
  Tell if a token is expired or not (TTL equals to 0).
50
58
  """
51
59
  return self.ttl == 0
52
60
 
53
61
  @classmethod
54
- def from_jwt(cls, token):
62
+ def from_jwt(cls, token: str) -> "Token":
55
63
  """
56
- Create a new token from a JWT, decoding it and caching it issued and
57
- expiration times.
64
+ Create a new token from a JWT, decoding it and caching its expiration time.
58
65
 
59
66
  :param token: (str) String containing the original encoded token which is the
60
67
  result of a POST request to the authentication endpoint.
@@ -65,8 +72,9 @@ class Token(object):
65
72
  raise TokenException(e)
66
73
 
67
74
  try:
68
- issued_at = datetime.fromtimestamp(payload["iat"])
69
- expires_at = datetime.fromtimestamp(payload["exp"])
70
- return cls(token, issued_at, expires_at)
75
+ return cls(
76
+ token=token,
77
+ expires_at=datetime.fromtimestamp(payload["exp"], tz=timezone.utc),
78
+ )
71
79
  except Exception as e:
72
80
  raise InvalidTokenException(e)
@@ -0,0 +1,78 @@
1
+ [tool.poetry]
2
+ name = "pyixapi"
3
+ version = "0.2.3"
4
+ description = "Python API client library for IX-API"
5
+ authors = ["Guillaume Mazoyer <oss@mazoyer.eu>"]
6
+ readme = "README.md"
7
+ license = "Apache-2.0"
8
+ packages = [{ include = "pyixapi" }]
9
+ classifiers = [
10
+ "Intended Audience :: Developers",
11
+ "Programming Language :: Python :: 3",
12
+ "Programming Language :: Python :: 3.8",
13
+ "Programming Language :: Python :: 3.9",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ ]
17
+
18
+ [tool.poetry.dependencies]
19
+ python = "^3.8"
20
+ PyJWT = ">=2.4.0,<2.9"
21
+ requests = ">=2.20.0,<3.0"
22
+
23
+ [tool.poetry.group.dev.dependencies]
24
+ pytest = "*"
25
+ ruff = "~0.2"
26
+
27
+ [tool.ruff]
28
+ line-length = 88
29
+
30
+ exclude = [
31
+ ".git",
32
+ ".tox",
33
+ ".venv",
34
+ "env",
35
+ "_build",
36
+ "build",
37
+ "dist",
38
+ "examples",
39
+ "__main__.py",
40
+ ]
41
+
42
+ [tool.ruff.lint]
43
+ preview = true
44
+
45
+ select = [
46
+ "C90", # mccabe complexity
47
+ "E", # pycodestyle errors
48
+ "W", # pycodestyle warnings
49
+ "F", # pyflakes
50
+ "I", # isort-like checks
51
+ "DTZ", # flake8-datetimez
52
+ "ICN", # flake8-import-conventions
53
+ "TCH", # flake8-type-checking
54
+ "T10", # flake8-debugger
55
+ "Q", # flake8-quotes
56
+ "YTT", # flake8-2020
57
+ ]
58
+
59
+ task-tags = ["FIXME", "TODO", "XXX"]
60
+
61
+ [tool.ruff.format]
62
+ quote-style = "double"
63
+ indent-style = "space"
64
+ skip-magic-trailing-comma = false
65
+ line-ending = "auto"
66
+
67
+ [tool.ruff.lint.isort]
68
+ known-first-party = ["pyixapi"]
69
+
70
+ [tool.ruff.lint.pycodestyle]
71
+ max-line-length = 88
72
+
73
+ [tool.ruff.lint.mccabe]
74
+ max-complexity = 31
75
+
76
+ [build-system]
77
+ requires = ["poetry-core"]
78
+ build-backend = "poetry.core.masonry.api"
@@ -1,4 +0,0 @@
1
- ---
2
- github: gmazoyer
3
- ko_fi: gmazoyer
4
- custom: https://paypal.me/GuillaumeMazoyer
@@ -1,19 +0,0 @@
1
- ---
2
- version: 2
3
- updates:
4
- - package-ecosystem: "pip"
5
- directory: "/"
6
- schedule:
7
- interval: "weekly"
8
- assignees:
9
- - "gmazoyer"
10
- labels:
11
- - "type: housekeeping"
12
- - package-ecosystem: "github-actions"
13
- directory: "/"
14
- schedule:
15
- interval: "weekly"
16
- assignees:
17
- - "gmazoyer"
18
- labels:
19
- - "type: housekeeping"
@@ -1,29 +0,0 @@
1
- # This workflows will upload a Python Package using Twine when a release is created
2
- # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3
-
4
- name: Upload Python Package
5
-
6
- on:
7
- release:
8
- types: [created]
9
-
10
- jobs:
11
- deploy:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v3
15
- - name: Set up Python
16
- uses: actions/setup-python@v4
17
- with:
18
- python-version: '3.x'
19
- - name: Install dependencies
20
- run: |
21
- python -m pip install --upgrade pip
22
- pip install build
23
- - name: Build package
24
- run: python -m build
25
- - name: Publish package
26
- uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e
27
- with:
28
- user: __token__
29
- password: ${{ secrets.PYPI_API_TOKEN }}
@@ -1,26 +0,0 @@
1
- name: Run Tests
2
-
3
- on:
4
- pull_request: {}
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- python: ["3.8", "3.9", "3.10", "3.11"]
15
- steps:
16
- - uses: actions/checkout@v3
17
- - name: Setup Python
18
- uses: actions/setup-python@v4
19
- with:
20
- python-version: ${{ matrix.python }}
21
- - name: Install dev requirements
22
- run: pip install -r requirements-dev.txt .
23
- - name: Run Linter
24
- run: black --diff --check pyixapi tests
25
- - name: Run Tests
26
- run: pytest
pyixapi-0.2.1/.gitignore DELETED
@@ -1,102 +0,0 @@
1
- # Byte-compiled / optimized / DLL files
2
- __pycache__/
3
- *.py[cod]
4
- *$py.class
5
-
6
- # C extensions
7
- *.so
8
-
9
- # Distribution / packaging
10
- .Python
11
- build/
12
- develop-eggs/
13
- dist/
14
- downloads/
15
- eggs/
16
- .eggs/
17
- lib64/
18
- lib/
19
- parts/
20
- sdist/
21
- var/
22
- wheels/
23
- *.egg-info/
24
- .installed.cfg
25
- *.egg
26
-
27
- # PyInstaller
28
- # Usually these files are written by a python script from a template
29
- # before PyInstaller builds the exe, so as to inject date/other infos into it.
30
- *.manifest
31
- *.spec
32
-
33
- # Installer logs
34
- pip-log.txt
35
- pip-delete-this-directory.txt
36
-
37
- # Unit test / coverage reports
38
- htmlcov/
39
- .tox/
40
- .coverage
41
- .coverage.*
42
- .cache
43
- nosetests.xml
44
- coverage.xml
45
- *.cover
46
- .hypothesis/
47
-
48
- # Translations
49
- *.mo
50
- *.pot
51
-
52
- # Django stuff:
53
- *.log
54
- local_settings.py
55
-
56
- # Flask stuff:
57
- instance/
58
- .webassets-cache
59
-
60
- # Scrapy stuff:
61
- .scrapy
62
-
63
- # Sphinx documentation
64
- docs/_build/
65
-
66
- # PyBuilder
67
- target/
68
-
69
- # Jupyter Notebook
70
- .ipynb_checkpoints
71
-
72
- # pyenv
73
- .python-version
74
-
75
- # celery beat schedule file
76
- celerybeat-schedule
77
-
78
- # SageMath parsed files
79
- *.sage.py
80
-
81
- # Environments
82
- .env
83
- .venv
84
- env/
85
- venv/
86
- ENV/
87
-
88
- # Spyder project settings
89
- .spyderproject
90
- .spyproject
91
-
92
- # Rope project settings
93
- .ropeproject
94
-
95
- # mkdocs documentation
96
- /site
97
-
98
- # mypy
99
- .mypy_cache/
100
-
101
- # Visual Studio Code settings
102
- .vscode/
pyixapi-0.2.1/PKG-INFO DELETED
@@ -1,79 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyixapi
3
- Version: 0.2.1
4
- Summary: IX-API client library
5
- Home-page: https://github.com/peering-manager/pyixapi
6
- Author: Guillaume Mazoyer
7
- Author-email: oss@mazoyer.eu
8
- License: Apache2
9
- Keywords: ix-api,internet-exchange,peering
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.8
14
- Classifier: Programming Language :: Python :: 3.9
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Programming Language :: Python :: 3.11
17
- Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
-
20
- # pyixapi
21
-
22
- Python API client library for [IX-API](https://ix-api.net/).
23
-
24
- Supported versions are:
25
-
26
- * [version 1](https://docs.ix-api.net/v1/)
27
- * [version 2](https://docs.ix-api.net/v2/)
28
-
29
- ## Installation
30
-
31
- To install run `pip install pyixapi`.
32
-
33
- Alternatively, you can clone the repo and run `python setup.py install`.
34
-
35
- ## Quick Start
36
-
37
- To begin, import pyixapi and instantiate the API.
38
-
39
- ```python
40
- import pyixapi
41
- ixapi = pyixapi.api(
42
- "https://api.de-cix.net/api/v1/",
43
- "3LH3G72VH7H1SGogEsFeQOPsGjOQotMUZQRt2pK7YbH",
44
- "cEtrt8s0vR0CsG0vpAmcaxtnolzZj7DEG0B7izvwPlV",
45
- )
46
- ixapi.authenticate()
47
- ```
48
-
49
- The first argument the `.api()` method takes is the IX-API URL. The second and
50
- third arguments are the API key and secret used for authentication.
51
-
52
- Authenticating will generate a pair of access and refresh tokens that can be
53
- passed as argument to the `.api()` method.
54
-
55
-
56
- ## Queries
57
-
58
- The pyixapi API is setup so that IX-API's endpoints are attributes of the
59
- `.api()` object. Each endpoint has a handful of methods available to carry out
60
- actions on the endpoint. For example, in order to query all the objects in the
61
- `network-service-configs` endpoint you would do the following:
62
-
63
- ```python
64
- >>> nsc = ixapi.network_service_configs.all()
65
- >>> for i in nsc:
66
- ... print(i)
67
- ...
68
- DXDB:PAS:00001
69
- DXDB:PAS:00002
70
- DXDB:PAS:00003
71
- DXDB:PAS:00004
72
- DXDB:PAS:00005
73
- DXDB:PAS:00006
74
- DXDB:PAS:00007
75
- DXDB:PAS:00008
76
- >>>
77
- ```
78
-
79
- Write queries are not implemented yet.
@@ -1,17 +0,0 @@
1
- # You can set these variables from the command line.
2
- SPHINXOPTS =
3
- SPHINXBUILD = sphinx-build
4
- SPHINXPROJ = pyixapi
5
- SOURCEDIR = .
6
- BUILDDIR = _build
7
-
8
- # Put it first so that "make" without argument is like "make help".
9
- help:
10
- @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
11
-
12
- .PHONY: help Makefile
13
-
14
- # Catch-all target: route all unknown targets to Sphinx using the new
15
- # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
16
- %: Makefile
17
- @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -1,74 +0,0 @@
1
- Custom Sessions
2
- ===============
3
-
4
- Custom sessions can be used to modify the default HTTP behavior. Below are a few examples, most of them from `here <https://hodovi.ch/blog/advanced-usage-python-requests-timeouts-retries-hooks/>`_.
5
-
6
- Headers
7
- *******
8
-
9
- To set a custom header on all requests. These headers are automatically merged with headers pyixapi sets itself.
10
-
11
- :Example:
12
-
13
- >>> import pyixapi
14
- >>> import requests
15
- >>> session = requests.Session()
16
- >>> session.headers = {"mycustomheader": "test"}
17
- >>> ixapi = pyixapi.api(
18
- ... "https://api.de-cix.net/api/v1/",
19
- ... "3LH3G72VH7H1SGogEsFeQOPsGjOQotMUZQRt2pK7YbH",
20
- ... "cEtrt8s0vR0CsG0vpAmcaxtnolzZj7DEG0B7izvwPlV",
21
- ... )
22
- >>> ixapi.http_session = session
23
-
24
-
25
- SSL Verification
26
- ****************
27
-
28
- To disable SSL verification. See `the docs <https://requests.readthedocs.io/en/stable/user/advanced/#ssl-cert-verification>`_.
29
-
30
- :Example:
31
-
32
- >>> import pyixapi
33
- >>> import requests
34
- >>> session = requests.Session()
35
- >>> session.verify = False
36
- >>> ixapi = pyixapi.api(
37
- ... "https://api.de-cix.net/api/v1/",
38
- ... "3LH3G72VH7H1SGogEsFeQOPsGjOQotMUZQRt2pK7YbH",
39
- ... "cEtrt8s0vR0CsG0vpAmcaxtnolzZj7DEG0B7izvwPlV",
40
- ... )
41
- >>> ixapi.http_session = session
42
-
43
-
44
- Timeouts
45
- ********
46
-
47
- Setting timeouts requires the use of Adapters.
48
-
49
- :Example:
50
-
51
- .. code-block:: python
52
-
53
- from requests.adapters import HTTPAdapter
54
-
55
- class TimeoutHTTPAdapter(HTTPAdapter):
56
- def __init__(self, *args, **kwargs):
57
- self.timeout = kwargs.get("timeout", 5)
58
- super().__init__(*args, **kwargs)
59
-
60
- def send(self, request, **kwargs):
61
- kwargs['timeout'] = self.timeout
62
- return super().send(request, **kwargs)
63
-
64
- adapter = TimeoutHTTPAdapter()
65
- session = requests.Session()
66
- session.mount("http://", adapter)
67
- session.mount("https://", adapter)
68
-
69
- ixapi = pyixapi.api(
70
- "https://api.de-cix.net/api/v1/",
71
- "3LH3G72VH7H1SGogEsFeQOPsGjOQotMUZQRt2pK7YbH",
72
- "cEtrt8s0vR0CsG0vpAmcaxtnolzZj7DEG0B7izvwPlV",
73
- )
74
- ixapi.http_session = session
@@ -1,158 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # pyixapi documentation build configuration file, created by
4
- # sphinx-quickstart on Sun Sep 18 18:31:27 2022.
5
- #
6
- # This file is execfile()d with the current directory set to its
7
- # containing dir.
8
- #
9
- # Note that not all possible configuration values are present in this
10
- # autogenerated file.
11
- #
12
- # All configuration values have a default; values that are commented out
13
- # serve to show the default.
14
-
15
- # If extensions (or modules to document with autodoc) are in another directory,
16
- # add these directories to sys.path here. If the directory is relative to the
17
- # documentation root, use os.path.abspath to make it absolute, like shown here.
18
- #
19
- import os
20
- import sys
21
-
22
- from pkg_resources import get_distribution
23
-
24
- sys.path.insert(0, os.path.abspath("../"))
25
-
26
-
27
- # -- General configuration ------------------------------------------------
28
-
29
- # If your documentation needs a minimal Sphinx version, state it here.
30
- #
31
- # needs_sphinx = '1.0'
32
-
33
- # Add any Sphinx extension module names here, as strings. They can be
34
- # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
35
- # ones.
36
- extensions = ["sphinx.ext.autodoc"]
37
-
38
- # Add any paths that contain templates here, relative to this directory.
39
- templates_path = ["_templates"]
40
-
41
- # The suffix(es) of source filenames.
42
- # You can specify multiple suffix as a list of string:
43
- #
44
- # source_suffix = ['.rst', '.md']
45
- source_suffix = ".rst"
46
-
47
- # The master toctree document.
48
- master_doc = "index"
49
-
50
- # General information about the project.
51
- project = "pyixapi"
52
- copyright = "2012, Guillaume Mazoyer"
53
- author = "Guillaume Mazoyer"
54
-
55
- # The version info for the project you're documenting, acts as replacement for
56
- # |version| and |release|, also used in various other places throughout the
57
- # built documents.
58
- # The full version, including alpha/beta/rc tags.
59
- release = get_distribution("pyixapi").version
60
- #
61
- # The short X.Y version.
62
- version = ".".join(release.split(".")[:2])
63
-
64
- # The language for content autogenerated by Sphinx. Refer to documentation
65
- # for a list of supported languages.
66
- #
67
- # This is also used if you do content translation via gettext catalogs.
68
- # Usually you set "language" from the command line for these cases.
69
- language = None
70
-
71
- # List of patterns, relative to source directory, that match files and
72
- # directories to ignore when looking for source files.
73
- # This patterns also effect to html_static_path and html_extra_path
74
- exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
75
-
76
- # The name of the Pygments (syntax highlighting) style to use.
77
- pygments_style = "sphinx"
78
-
79
- # If true, `todo` and `todoList` produce output, else they produce nothing.
80
- todo_include_todos = False
81
-
82
-
83
- # -- Options for HTML output ----------------------------------------------
84
-
85
- # The theme to use for HTML and HTML Help pages. See the documentation for
86
- # a list of builtin themes.
87
- #
88
- # html_theme = 'classic'
89
-
90
- # Theme options are theme-specific and customize the look and feel of a theme
91
- # further. For a list of options available for each theme, see the
92
- # documentation.
93
- #
94
- # html_theme_options = {}
95
-
96
- # Add any paths that contain custom static files (such as style sheets) here,
97
- # relative to this directory. They are copied after the builtin static files,
98
- # so a file named "default.css" will overwrite the builtin "default.css".
99
- # html_static_path = ['_static']
100
-
101
- html_sidebars = {
102
- "**": ["globaltoc.html", "relations.html", "sourcelink.html", "searchbox.html"]
103
- }
104
-
105
- # -- Options for HTMLHelp output ------------------------------------------
106
-
107
- # Output file base name for HTML help builder.
108
- htmlhelp_basename = "pyixapidoc"
109
-
110
-
111
- # -- Options for LaTeX output ---------------------------------------------
112
-
113
- latex_elements = {
114
- # The paper size ('letterpaper' or 'a4paper').
115
- #
116
- # 'papersize': 'letterpaper',
117
- # The font size ('10pt', '11pt' or '12pt').
118
- #
119
- # 'pointsize': '10pt',
120
- # Additional stuff for the LaTeX preamble.
121
- #
122
- # 'preamble': '',
123
- # Latex figure (float) alignment
124
- #
125
- # 'figure_align': 'htbp',
126
- }
127
-
128
- # Grouping the document tree into LaTeX files. List of tuples
129
- # (source start file, target name, title,
130
- # author, documentclass [howto, manual, or own class]).
131
- latex_documents = [
132
- (master_doc, "pyixapi.tex", "pyixapi Documentation", "Guillaume Mazoyer", "manual"),
133
- ]
134
-
135
-
136
- # -- Options for manual page output ---------------------------------------
137
-
138
- # One entry per manual page. List of tuples
139
- # (source start file, name, description, authors, manual section).
140
- man_pages = [(master_doc, "pyixapi", "pyixapi Documentation", [author], 1)]
141
-
142
-
143
- # -- Options for Texinfo output -------------------------------------------
144
-
145
- # Grouping the document tree into Texinfo files. List of tuples
146
- # (source start file, target name, title, author,
147
- # dir menu entry, description, category)
148
- texinfo_documents = [
149
- (
150
- master_doc,
151
- "pyixapi",
152
- "pyixapi Documentation",
153
- author,
154
- "pyixapi",
155
- "A python library for IX-API.",
156
- "Miscellaneous",
157
- ),
158
- ]
@@ -1,5 +0,0 @@
1
- Endpoint
2
- ========
3
-
4
- .. autoclass:: pyixapi.core.endpoint.Endpoint
5
- :members:
@@ -1,29 +0,0 @@
1
- .. toctree::
2
- :maxdepth: 2
3
- :caption: Contents:
4
-
5
- endpoint
6
- response
7
- request
8
- IPAM
9
-
10
- TL;DR
11
- =====
12
- Instantiate the :py:class:`.Api`. Use the methods available on :py:class:`.Endpoint` to return :py:class:`.Record` objects.
13
-
14
- API
15
- ===
16
-
17
- .. autoclass:: pyixapi.core.api.Api
18
- :members:
19
-
20
- App
21
- ===
22
-
23
- .. autoclass:: pyixapi.core.app.App
24
- :members:
25
-
26
- Indices and tables
27
- ==================
28
-
29
- * :ref:`genindex`
@@ -1,8 +0,0 @@
1
- Request
2
- ========
3
-
4
- .. autoclass:: pyixapi.core.query.RequestError
5
- :members:
6
-
7
- .. autoclass:: pyixapi.core.query.ContentError
8
- :members:
@@ -1,8 +0,0 @@
1
- Response
2
- ========
3
-
4
- .. autoclass:: pyixapi.core.response.Record
5
- :members:
6
-
7
- .. autoclass:: pyixapi.core.response.RecordSet
8
- :members:
@@ -1,11 +0,0 @@
1
- from pkg_resources import DistributionNotFound, get_distribution
2
-
3
- from pyixapi.core.api import API as api
4
- from pyixapi.core.query import ContentError, RequestError
5
-
6
- try:
7
- __version__ = get_distribution(__name__).version
8
- except DistributionNotFound:
9
- pass
10
-
11
- __all__ = ("api", "ContentError", "RequestError")
@@ -1,38 +0,0 @@
1
- .gitignore
2
- LICENSE
3
- README.md
4
- pyproject.toml
5
- requirements-dev.txt
6
- requirements.txt
7
- setup.py
8
- .github/FUNDING.yml
9
- .github/dependabot.yml
10
- .github/workflows/publish.yml
11
- .github/workflows/tests.yml
12
- docs/Makefile
13
- docs/advanced.rst
14
- docs/conf.py
15
- docs/endpoint.rst
16
- docs/index.rst
17
- docs/request.rst
18
- docs/response.rst
19
- pyixapi/__init__.py
20
- pyixapi/models.py
21
- pyixapi.egg-info/PKG-INFO
22
- pyixapi.egg-info/SOURCES.txt
23
- pyixapi.egg-info/dependency_links.txt
24
- pyixapi.egg-info/not-zip-safe
25
- pyixapi.egg-info/requires.txt
26
- pyixapi.egg-info/top_level.txt
27
- pyixapi/core/__init__.py
28
- pyixapi/core/api.py
29
- pyixapi/core/endpoint.py
30
- pyixapi/core/query.py
31
- pyixapi/core/response.py
32
- pyixapi/core/token.py
33
- pyixapi/core/util.py
34
- tests/__init__.py
35
- tests/test_api.py
36
- tests/util.py
37
- tests/fixtures/api/authenticate.json
38
- tests/fixtures/api/refresh_authentication.json
@@ -1 +0,0 @@
1
-
@@ -1,2 +0,0 @@
1
- requests<3.0,>=2.20.0
2
- PyJWT<2.9,>=2.4.0
@@ -1 +0,0 @@
1
- pyixapi
@@ -1,8 +0,0 @@
1
- # See PEP 518 for the spec of this file
2
- # https://www.python.org/dev/peps/pep-0518/
3
-
4
- [tool.black]
5
- target_version = ["py38", "py39", "py310", "py311"]
6
-
7
- [tool.isort]
8
- profile = "black"
@@ -1,2 +0,0 @@
1
- black~=23.7
2
- pytest==7.4.*
@@ -1,2 +0,0 @@
1
- PyJWT>=2.4.0,<2.9
2
- requests>=2.20.0,<3.0
pyixapi-0.2.1/setup.cfg DELETED
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
pyixapi-0.2.1/setup.py DELETED
@@ -1,33 +0,0 @@
1
- from pathlib import Path
2
-
3
- from setuptools import find_packages, setup
4
-
5
- d = Path(__file__).parent
6
- long_description = (d / "README.md").read_text()
7
-
8
- setup(
9
- name="pyixapi",
10
- description="IX-API client library",
11
- long_description=long_description,
12
- long_description_content_type="text/markdown",
13
- url="https://github.com/peering-manager/pyixapi",
14
- author="Guillaume Mazoyer",
15
- author_email="oss@mazoyer.eu",
16
- license="Apache2",
17
- include_package_data=True,
18
- use_scm_version=True,
19
- setup_requires=["setuptools_scm"],
20
- packages=find_packages(exclude=["tests", "tests.*"]),
21
- install_requires=["requests>=2.20.0,<3.0", "PyJWT>=2.4.0,<2.9"],
22
- zip_safe=False,
23
- keywords=["ix-api", "internet-exchange", "peering"],
24
- classifiers=[
25
- "Intended Audience :: Developers",
26
- "Development Status :: 5 - Production/Stable",
27
- "Programming Language :: Python :: 3",
28
- "Programming Language :: Python :: 3.8",
29
- "Programming Language :: Python :: 3.9",
30
- "Programming Language :: Python :: 3.10",
31
- "Programming Language :: Python :: 3.11",
32
- ],
33
- )
File without changes
@@ -1,4 +0,0 @@
1
- {
2
- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2NjM5NjE0MDAsImV4cCI6MTY2Mzk2MjMwMCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoidGVzdEBleGFtcGxlLmNvbSJ9.jPZ4TMh9mFGu2Ebgz-UO3bd5wrAJDyOjJaul1tq0AoI",
3
- "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2NjM5NjE0MDAsImV4cCI6MTY2NDU2NjIwMCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoidGVzdEBleGFtcGxlLmNvbSJ9.NCIzCxKjceLGfHb7ozJ5KsLw0WSlWHXx3dPGx8n8P0Q"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2NjQwNDc4MDAsImV4cCI6MTY2NDA0ODcwMCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoidGVzdEBleGFtcGxlLmNvbSJ9._PeLD8F8SlVJKZcBAQ7a5ONsFYXWl9Q_UjKJLGS-uAI",
3
- "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2NjQwNDc4MDAsImV4cCI6MTY2NDY1MjYwMCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoidGVzdEBleGFtcGxlLmNvbSJ9.xHKO5CyRQbbLEAvuiuk4srb7px8G-2JScjBy-bVTqsg"
4
- }
@@ -1,86 +0,0 @@
1
- import unittest
2
- from unittest.mock import patch
3
-
4
- import pyixapi
5
-
6
- from .util import Response
7
-
8
- host = "https://api.example.net/v1/"
9
-
10
- def_args = (
11
- "-GnNlMD8hBuxSSUJmpbfUkss9dyOKfTV1SnZibNyyr4",
12
- "XKq8M6NVh5lCbPJ2Ml1h7V93QNIMsGVBfM6g2nRZF-E",
13
- )
14
-
15
-
16
- class ApiTestCase(unittest.TestCase):
17
- @patch(
18
- "requests.sessions.Session.post",
19
- return_value=Response(fixture="api/authenticate.json"),
20
- )
21
- def test_authenticate(self, *_):
22
- api = pyixapi.api(host, *def_args)
23
- r = api.authenticate()
24
-
25
- self.assertIsNotNone(r)
26
- self.assertIsNotNone(api.access_token)
27
- self.assertIsNotNone(api.refresh_token)
28
-
29
- @patch(
30
- "requests.sessions.Session.post",
31
- return_value=Response(fixture="api/refresh_authentication.json"),
32
- )
33
- def test_refresh_authentication(self, *_):
34
- api = pyixapi.api(host, *def_args)
35
- api.authenticate()
36
- r = api.refresh_authentication()
37
-
38
- self.assertIsNotNone(r)
39
- self.assertIsNotNone(api.access_token)
40
- self.assertIsNotNone(api.refresh_token)
41
-
42
-
43
- class ApiVersionTestCase(unittest.TestCase):
44
- class ResponseWithFailure:
45
- ok = False
46
- status_code = 404
47
- url = host
48
- text = "Not found"
49
-
50
- class ResponseWithSuccess:
51
- ok = True
52
-
53
- def json(self):
54
- return {"status": "pass", "version": 2}
55
-
56
- @patch(
57
- "requests.sessions.Session.get",
58
- return_value=ResponseWithFailure(),
59
- )
60
- def test_api_version_1(self, *_):
61
- api = pyixapi.api(host, *def_args)
62
- self.assertEqual(api.version, 1)
63
-
64
- @patch(
65
- "requests.sessions.Session.get",
66
- return_value=ResponseWithSuccess(),
67
- )
68
- def test_api_version(self, *_):
69
- api = pyixapi.api(host, *def_args)
70
- self.assertEqual(api.version, 2)
71
-
72
-
73
- class ApiHealthTestCase(unittest.TestCase):
74
- class ResponseWithHealth:
75
- ok = True
76
-
77
- def json(self):
78
- return {"status": "pass", "version": "2"}
79
-
80
- @patch(
81
- "requests.sessions.Session.get",
82
- return_value=ResponseWithHealth(),
83
- )
84
- def test_api_status(self, *_):
85
- api = pyixapi.api(host, *def_args)
86
- self.assertEqual(api.health()["status"], "pass")
@@ -1,15 +0,0 @@
1
- import json
2
-
3
-
4
- class Response(object):
5
- def __init__(self, fixture=None, status_code=200, ok=True, content=None):
6
- self.status_code = status_code
7
- self.content = json.dumps(content) if content else self.load_fixture(fixture)
8
- self.ok = ok
9
-
10
- def load_fixture(self, path):
11
- with open(f"tests/fixtures/{path}", "r") as f:
12
- return f.read()
13
-
14
- def json(self):
15
- return json.loads(self.content)
File without changes
File without changes
File without changes