add: demo server and client

This commit is contained in:
Charles
2024-04-06 20:45:15 -07:00
parent 5a149bc922
commit 72effb5b2a
100 changed files with 11603 additions and 62 deletions

192
README.md
View File

@@ -1,4 +1,4 @@
*/# PeerNet -- peer-to-peer communication without the network
# PeerNet -- peer-to-peer communication without the network
PeerNet is a protocol and server software which let clients communicate directly with each other without required a lot of configuration or system permissions. It leverages WebRTC to create data channels between peers, and uses a simple protocol to let clients advertise services for other clients to connect with. Initially developed as an attempt to simplify a home security system, the reference client implementations offer:
@@ -19,79 +19,147 @@ One minor goal in this API design is to minimize the number of messages that nee
Sample server flow:
```pyton
import requests
1. Server creates an auth token; this is secret, and is used to restrict actions related to the server such as updating/deleting it, or listing pending knocks
2. Server send a POST to /v1/servers with the server object, including a list of services offered
3. Server begins polling /v1/servers/{server}/services/{service}/knocks for client attempts to connect
4. When a knock is recieved, a worker should be spawned to handle the connection
url = 'https://myserver.local'
When a client connects, the standard WebRTC negotation commences. Restating from [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Connectivity#session_descriptions):
1. Peer connection is created in client (caller, in WebRTC parliance)
2. Attach channels to it (i.e., a data channel)
3. Client creates an offer; they set the 'local description' to the offer
4. Client sends request to signaling server (peernet server)
5. The peer recieves the request and sets remote description to the offer
6. The peer creates an answer and sets it to 'local description'
7. The peer sends the answer to the signaling server (peernet server)
8. Client recieves the answer and sets it as remote description
In steps 3 and 6, the client and peer indicate a STUN/TURN server and begin generating ICE candidates. This is where the mgaic of bridging firewalls happens. The candidates will trickle from each system, and must be passed through the signaling server to the other system. The hope is that eventually both the client and peer find an ICE candidate they can use to exchange data without a middle man.
Once the ICE negotation has completed, data can flow according to the service protocol. Using the Python aiortc library, this might look like:
```
async def handle_offer(knock, peernetClient):
pc = RTCPeerConnection()
# Define our handlers
done = False
@pc.on("datachannel")
def on_datachannel(channel):
@channel.on("message")
def on_message(message):
# Process the message, and send a response
channel.send("pong" + message[4:])
@pc.on("connectionstatechange")
async def on_connectionstatechange():
if pc.connectionState == "failed":
done = True
await pc.close()
@pc.on("icecandidate")
async def on_icecandidate(candidate):
peernetClient.post("/v1/sessions/{knock.offer.name}/candidates", {
"candidate": candidate_to_sdp(obj),
"sdpMid": obj.sdpMid,
"sdpLineIndex": obj.sdpMLineIndex,
})
# Add the remote offer
offer = RTCSessionDescription(sdp=knock.offer.sdp, type=knock.offer.sdpType)
await pc.setRemoteDescription(offer)
# Create an answer
answer = await pc.createAnswer()
await pc.setLocalDescription(answer)
# Send the answer
session_id = uuid.new()
knock.answer = {
"name": session_id,
"sdp": answer.sdp,
"sdpType", answer.sdptype"
}
peernetClient.patch(knock.name, knock)
while not done:
candidates = peernetClient.get("/v1/sessions/{session_id}/claim/candidates")
for candidate in candidates:
ice_candidate = candidate_from_sdp(candidate.candidate)
ice_candidate.sdpMid = candidate.sdpMid
ice_candidate.sdpMLineIndex = candidate.sdpLineIndex
await pc.addIceCandidate(candidate)
response = requests.post(url + '/server', '''
{
"unique_id": "
}
''')
```
The protocol is define below in Protobuf, but is also availabe [here] in OpenAPI format.
```proto2
syntax = "proto2";
package peernet
server.py
```pyton
import requests
import instance.serve
import uuid
service PeerNetService {
rpc CreateRoom(CreateRoomRequest) returns (CreateRoomResponse);
rpc DeleteRoom(DeleteRoomRequest) return (DeleteRoomResponse);
url = 'https://myserver.local/v1'
auth_token = uuid.uuid4()
rpc CreateServer(CreateServerRequest) returns (CreateServerResponse);
rpc DeleteServer(DeleteServerRequest) returns (DeleteServerResponse);
rpc ListServers(ListServersRequest) returns (ListServersResponse);
rpc CreateService(CreateServiceRequest) returns (CreateServiceResponse);
rpc DeleteService(DeleteServiceRequest) returns (DeleteServiceResponse);
rpc UpdateService(UpdateServiceRequest) returns (UpdateServiceResponse);
rpc CreateKnock(CreateKnockRequest) returns (CreateKnockResponse);
rpc DeleteKnock(DeleteKnockRequest) returns (DeleteKnockResponse);
rpc GetKnock(GetKnockRequest) returns (Knock);
rpc ListKnocks(ListKnocksRequest) returns (ListKnocksResponse);
# This call creates a few things as a side effect:
# 1. The rooms 'the-good-place' and 'the-bad-place'
# 2. A server with the display_name "Chidi"
# 3. A service beloning to that server
create_server_response = requests.post(url + '/servers', '''
{
"unique_id": "my-public-name",
"rooms": [
"the-good-place",
"the-bad-place",
],
"auth_token": %s
"display_name": "Chidi",
"services": [
{
"protocol": "peernet.http",
"version": "1.1",
},
],
}
''' % auth_token)
message Room {
string unique_id = 1;
string display_name = 2;
}
# Response contains a token we use to authorize ourselves
auth_header = {"Authorization": auth_token}
message Server {
string unique_id = 1;
# Poll for clients, and spin off a helper when one tries to connect
while True:
claim_knocks_response = request.get(
url + "/servers/%s/claim_knocks" % create_server_response.unique_id,
# The filter lets us ignore service we don't support
'''
"filter": "service.name=\"peernet.http\" AND service.version=\"1.1\""
'''
headers=auth_header,
)
list_knocks_json = list_knocks_response.json()
string room = 2;
string display_name = 2;
}
for knock in list_knocks_json["knocks"]:
# Spin off a process to handle the knock
p = Process(target=instance.serve, args=(knock))
p.start()
time.sleep(1)
message Service {
string protocol = 1;
string version = 2;
```
// Used to define custom fields per-protocol/version.
// We use unverified extensions because this system is meant
// to be distributed, with no central owner, hence, no singular
// authority to hand out field numbers. Instead, implementations
// should use the protocol/version to scope what values are expected.
extensions 100 to max [verification = UNVERIFIED];
}
instance.py
```
import asyncio
from multiprocessing import Process
from aiortc import RTCIceCandidate, RTCPeerConnection, RTCSessionDescription
message Knock {
repeated IceCandidate ice_candidates = 1;
}
async def serve(url, auth_header, knock):
peer_connection = RTCPeerConnection()
await peer_connection.set_remote_description(knock.client_session_description)
await pc.setLocalDescription(await peer_connection.createAnswer())
for ice_candidate in knock['ice_candidates']:
await peer_connection.addIceCandidate(ice_candidate)
# Gather local ICE candidates
message IceCandidate {
// Copied from https://pkg.go.dev/github.com/pion/webrtc/v4#ICECandidateInit
string candidate = 1;
optional string sdp_mid = 2;
optional int32 sdp_line_index = 3;
optional string username_fragment = 4;
}
```
```

72
demo_server/.dockerignore Normal file
View File

@@ -0,0 +1,72 @@
.travis.yaml
.openapi-generator-ignore
README.md
tox.ini
git_push.sh
test-requirements.txt
setup.py
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
venv/
.python-version
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
#Ipython Notebook
.ipynb_checkpoints

66
demo_server/.gitignore vendored Normal file
View File

@@ -0,0 +1,66 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
venv/
.venv/
.python-version
.pytest_cache
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
#Ipython Notebook
.ipynb_checkpoints

View File

@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@@ -0,0 +1,32 @@
.dockerignore
.gitignore
.travis.yml
Dockerfile
README.md
git_push.sh
openapi_server/__init__.py
openapi_server/__main__.py
openapi_server/controllers/__init__.py
openapi_server/controllers/peer_net_service_controller.py
openapi_server/controllers/security_controller.py
openapi_server/encoder.py
openapi_server/models/__init__.py
openapi_server/models/base_model.py
openapi_server/models/claim_ice_candidates_response.py
openapi_server/models/google_protobuf_any.py
openapi_server/models/ice_candidate.py
openapi_server/models/ice_session_description.py
openapi_server/models/knock.py
openapi_server/models/list_knocks_response.py
openapi_server/models/room.py
openapi_server/models/server.py
openapi_server/models/service.py
openapi_server/models/status.py
openapi_server/openapi/openapi.yaml
openapi_server/test/__init__.py
openapi_server/typing_utils.py
openapi_server/util.py
requirements.txt
setup.py
test-requirements.txt
tox.ini

View File

@@ -0,0 +1 @@
7.4.0

14
demo_server/.travis.yml Normal file
View File

@@ -0,0 +1,14 @@
# ref: https://docs.travis-ci.com/user/languages/python
language: python
python:
- "3.2"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
# command to install dependencies
install: "pip install -r requirements.txt"
# command to run tests
script: nosetests

16
demo_server/Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
FROM python:3-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip3 install --no-cache-dir -r requirements.txt
COPY . /usr/src/app
EXPOSE 8080
ENTRYPOINT ["python3"]
CMD ["-m", "openapi_server"]

49
demo_server/README.md Normal file
View File

@@ -0,0 +1,49 @@
# OpenAPI generated server
## Overview
This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://openapis.org) from a remote server, you can easily generate a server stub. This
is an example of building a OpenAPI-enabled Flask server.
This example uses the [Connexion](https://github.com/zalando/connexion) library on top of Flask.
## Requirements
Python 3.5.2+
## Usage
To run the server, please execute the following from the root directory:
```
pip3 install -r requirements.txt
python3 -m openapi_server
```
and open your browser to here:
```
http://localhost:8080/ui/
```
Your OpenAPI definition lives here:
```
http://localhost:8080/openapi.json
```
To launch the integration tests, use tox:
```
sudo pip install tox
tox
```
## Running with Docker
To run the server on a Docker container, please execute the following from the root directory:
```bash
# building the image
docker build -t openapi_server .
# starting up a container
docker run -p 8080:8080 openapi_server
```

View File

@@ -0,0 +1,38 @@
# NOTE: This file is auto generated by OpenAPI Generator.
# URL: https://openapi-generator.tech
#
# ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: openapi_client Python package
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest

66
demo_server/demo_client/.gitignore vendored Normal file
View File

@@ -0,0 +1,66 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
venv/
.venv/
.python-version
.pytest_cache
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
#Ipython Notebook
.ipynb_checkpoints

View File

@@ -0,0 +1,31 @@
# NOTE: This file is auto generated by OpenAPI Generator.
# URL: https://openapi-generator.tech
#
# ref: https://docs.gitlab.com/ee/ci/README.html
# ref: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
stages:
- test
.pytest:
stage: test
script:
- pip install -r requirements.txt
- pip install -r test-requirements.txt
- pytest --cov=openapi_client
pytest-3.7:
extends: .pytest
image: python:3.7-alpine
pytest-3.8:
extends: .pytest
image: python:3.8-alpine
pytest-3.9:
extends: .pytest
image: python:3.9-alpine
pytest-3.10:
extends: .pytest
image: python:3.10-alpine
pytest-3.11:
extends: .pytest
image: python:3.11-alpine

View File

@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@@ -0,0 +1,44 @@
.github/workflows/python.yml
.gitignore
.gitlab-ci.yml
.travis.yml
README.md
docs/ClaimIceCandidatesResponse.md
docs/GoogleProtobufAny.md
docs/IceCandidate.md
docs/IceSessionDescription.md
docs/Knock.md
docs/ListKnocksResponse.md
docs/PeerNetServiceApi.md
docs/Room.md
docs/Server.md
docs/Service.md
docs/Status.md
git_push.sh
openapi_client/__init__.py
openapi_client/api/__init__.py
openapi_client/api/peer_net_service_api.py
openapi_client/api_client.py
openapi_client/api_response.py
openapi_client/configuration.py
openapi_client/exceptions.py
openapi_client/models/__init__.py
openapi_client/models/claim_ice_candidates_response.py
openapi_client/models/google_protobuf_any.py
openapi_client/models/ice_candidate.py
openapi_client/models/ice_session_description.py
openapi_client/models/knock.py
openapi_client/models/list_knocks_response.py
openapi_client/models/room.py
openapi_client/models/server.py
openapi_client/models/service.py
openapi_client/models/status.py
openapi_client/py.typed
openapi_client/rest.py
pyproject.toml
requirements.txt
setup.cfg
setup.py
test-requirements.txt
test/__init__.py
tox.ini

View File

@@ -0,0 +1 @@
7.4.0

View File

@@ -0,0 +1,17 @@
# ref: https://docs.travis-ci.com/user/languages/python
language: python
python:
- "3.7"
- "3.8"
- "3.9"
- "3.10"
- "3.11"
# uncomment the following if needed
#- "3.11-dev" # 3.11 development branch
#- "nightly" # nightly build
# command to install dependencies
install:
- "pip install -r requirements.txt"
- "pip install -r test-requirements.txt"
# command to run tests
script: pytest --cov=openapi_client

View File

@@ -0,0 +1,124 @@
# openapi-client
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 0.0.1
- Package version: 1.0.0
- Generator version: 7.4.0
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
## Requirements.
Python 3.7+
## Installation & Usage
### pip install
If the python package is hosted on a repository, you can install directly using:
```sh
pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git
```
(you may need to run `pip` with root permission: `sudo pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git`)
Then import the package:
```python
import openapi_client
```
### Setuptools
Install via [Setuptools](http://pypi.python.org/pypi/setuptools).
```sh
python setup.py install --user
```
(or `sudo python setup.py install` to install the package for all users)
Then import the package:
```python
import openapi_client
```
### Tests
Execute `pytest` to run the tests.
## Getting Started
Please follow the [installation procedure](#installation--usage) and then run the following:
```python
import openapi_client
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
session = 'session_example' # str | The session id.
try:
api_response = api_instance.peer_net_service_claim_ice_candidates(session)
print("The response of PeerNetServiceApi->peer_net_service_claim_ice_candidates:\n")
pprint(api_response)
except ApiException as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_claim_ice_candidates: %s\n" % e)
```
## Documentation for API Endpoints
All URIs are relative to *http://localhost*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*PeerNetServiceApi* | [**peer_net_service_claim_ice_candidates**](docs/PeerNetServiceApi.md#peer_net_service_claim_ice_candidates) | **GET** /v1/sessions/{session}/claim/candidates |
*PeerNetServiceApi* | [**peer_net_service_create_ice_candidate**](docs/PeerNetServiceApi.md#peer_net_service_create_ice_candidate) | **POST** /v1/sessions/{session}/candidates |
*PeerNetServiceApi* | [**peer_net_service_create_knock**](docs/PeerNetServiceApi.md#peer_net_service_create_knock) | **POST** /v1/servers/{server}/services/{service}/knocks |
*PeerNetServiceApi* | [**peer_net_service_create_server**](docs/PeerNetServiceApi.md#peer_net_service_create_server) | **POST** /v1/servers |
*PeerNetServiceApi* | [**peer_net_service_create_service**](docs/PeerNetServiceApi.md#peer_net_service_create_service) | **POST** /v1/servers/{server}/services |
*PeerNetServiceApi* | [**peer_net_service_delete_server**](docs/PeerNetServiceApi.md#peer_net_service_delete_server) | **DELETE** /v1/servers/* |
*PeerNetServiceApi* | [**peer_net_service_delete_service**](docs/PeerNetServiceApi.md#peer_net_service_delete_service) | **DELETE** /v1/servers/{server}/services/{service} |
*PeerNetServiceApi* | [**peer_net_service_get_knock**](docs/PeerNetServiceApi.md#peer_net_service_get_knock) | **GET** /v1/servers/{server}/services/{service}/knocks/{knock} |
*PeerNetServiceApi* | [**peer_net_service_get_room**](docs/PeerNetServiceApi.md#peer_net_service_get_room) | **GET** /v1/rooms/{room} |
*PeerNetServiceApi* | [**peer_net_service_list_knocks**](docs/PeerNetServiceApi.md#peer_net_service_list_knocks) | **GET** /v1/servers/{server}/services/{service}/knocks |
*PeerNetServiceApi* | [**peer_net_service_update_knock**](docs/PeerNetServiceApi.md#peer_net_service_update_knock) | **PATCH** /v1/servers/{server}/services/{service}/knocks/{knock} |
## Documentation For Models
- [ClaimIceCandidatesResponse](docs/ClaimIceCandidatesResponse.md)
- [GoogleProtobufAny](docs/GoogleProtobufAny.md)
- [IceCandidate](docs/IceCandidate.md)
- [IceSessionDescription](docs/IceSessionDescription.md)
- [Knock](docs/Knock.md)
- [ListKnocksResponse](docs/ListKnocksResponse.md)
- [Room](docs/Room.md)
- [Server](docs/Server.md)
- [Service](docs/Service.md)
- [Status](docs/Status.md)
<a id="documentation-for-authorization"></a>
## Documentation For Authorization
Endpoints do not require authorization.
## Author

View File

@@ -0,0 +1,112 @@
import time
import asyncio
from multiprocessing import Process
from aiortc import RTCIceCandidate, RTCPeerConnection, RTCSessionDescription
from openapi_client.rest import ApiException
from pprint import pprint
from aiortc import RTCPeerConnection, RTCSessionDescription
from aiortc.sdp import candidate_from_sdp, candidate_to_sdp
import uuid
import openapi_client
# Defining the host is optional and defaults to http://127.0.0.1:8080
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://127.0.0.1:8080"
)
server_name="myserver"
service_name="http1"
def serve(peernet, knock, server_name):
async def server_internal():
pc = RTCPeerConnection()
# Define our handlers
done = False
session = "%s" % uuid.uuid4()
@pc.on("datachannel")
def on_datachannel(channel):
@channel.on("message")
def on_message(message):
# Process the message, and send a response
channel.send("pong" + message[4:])
@pc.on("connectionstatechange")
async def on_connectionstatechange():
if pc.connectionState == "failed":
done = True
await pc.close()
@pc.on("icecandidate")
async def on_icecandidate(candidate):
peernet.peer_net_service_create_ice_candidatge(session=knock.offer.name, ice_candidate={
"candidate": candidate_to_sdp(obj),
"sdpMid": obj.sdpMid,
"sdpLineIndex": obj.sdpMLineIndex,
})
# Add the remote offer
offer = RTCSessionDescription(sdp=knock.offer.sdp, type="offer")
await pc.setRemoteDescription(offer)
# Create an answer
answer = await pc.createAnswer()
await pc.setLocalDescription(answer)
# Send the answer
session_id = "%s" % uuid.uuid4()
knock.answer = {
"name": session_id,
"sdp": answer.sdp,
"sdpType": answer.type,
}
peernet.peer_net_service_update_knock(server_name, service_name, knock.name, knock2=knock)
while not done:
resp = peernet.peer_net_service_claim_ice_candidates(session_id)
if resp.ice_candidates != None:
time.sleep(1)
continue
for candidate in resp.ice_candidates:
ice_candidate = candidate_from_sdp(candidate.candidate)
ice_candidate.sdpMid = candidate.sdpMid
ice_candidate.sdpMLineIndex = candidate.sdpLineIndex
await pc.addIceCandidate(candidate)
coro = server_internal()
# run event loop
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(coro)
except KeyboardInterrupt:
pass
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
peernet = openapi_client.PeerNetServiceApi(api_client)
resp = peernet.peer_net_service_create_server(server={
"name": server_name,
"rooms": ["room1"],
"services": [
{
"name": service_name,
"protocol": "http",
"version": "1.0",
},
],
})
while True:
print("Checking for knocks")
resp = peernet.peer_net_service_list_knocks(server=server_name, service=service_name)
for knock in resp.knocks:
print("Processing %s", knock)
p = Process(target=serve, args=(peernet, knock, server_name))
p.start()
time.sleep(5)

View File

@@ -0,0 +1,103 @@
import time
import asyncio
from multiprocessing import Process
from aiortc import RTCIceCandidate, RTCPeerConnection, RTCSessionDescription
from openapi_client.rest import ApiException
from pprint import pprint
from aiortc import RTCPeerConnection, RTCSessionDescription
from aiortc.sdp import candidate_from_sdp, candidate_to_sdp
import uuid
import openapi_client
async def run():
# Defining the host is optional and defaults to http://127.0.0.1:8080
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://127.0.0.1:8080"
)
server_name="myserver"
service_name="http1"
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
peernet = openapi_client.PeerNetServiceApi(api_client)
pc = RTCPeerConnection()
channel = pc.createDataChannel("http1")
# Define our handlers
done = False
session = "%s" % uuid.uuid4()
@channel.on("open")
def on_open():
print("Connection established!")
@pc.on("datachannel")
def on_datachannel(channel):
@channel.on("message")
def on_message(message):
# Process the message, and send a response
channel.send("<html><body>Hello world</body></html>")
@pc.on("connectionstatechange")
async def on_connectionstatechange():
if pc.connectionState == "failed":
done = True
await pc.close()
@pc.on("icecandidate")
async def on_icecandidate(candidate):
peernet.peer_net_service_create_ice_candidatge(session=knock.offer.name, ice_candidate={
"candidate": candidate_to_sdp(obj),
"sdpMid": obj.sdpMid,
"sdpLineIndex": obj.sdpMLineIndex,
})
offer = await pc.createOffer()
await pc.setLocalDescription(offer)
knock_name = "%s" % uuid.uuid4()
peernet.peer_net_service_create_knock(server=server_name, service=service_name, knock={
"name": knock_name,
"offer": {
"name": session,
"sdp": offer.sdp,
},
})
# Poll the server waiting for answer
answer = None
while True:
print("Checking for knocks")
resp = peernet.peer_net_service_get_knock(server_name, service_name, knock_name)
print("%s", resp)
if resp.answer != None:
answer = resp.answer
break
time.sleep(1)
await pc.setRemoteDescription(RTCSessionDescription(sdp=answer.sdp, type="answer"))
# Start connecting ice candidates!
while not done:
resp = peernet.peer_net_service_claim_ice_candidates(session)
if resp.ice_candidates != None:
time.sleep(1)
continue
for candidate in resp.ice_candidates:
ice_candidate = candidate_from_sdp(candidate.candidate)
ice_candidate.sdpMid = candidate.sdpMid
ice_candidate.sdpMLineIndex = candidate.sdpLineIndex
await pc.addIceCandidate(candidate)
coro = run()
# run event loop
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(coro)
except KeyboardInterrupt:
pass

View File

@@ -0,0 +1,29 @@
# ClaimIceCandidatesResponse
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**ice_candidates** | [**List[IceCandidate]**](IceCandidate.md) | | [optional]
## Example
```python
from openapi_client.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
# TODO update the JSON string below
json = "{}"
# create an instance of ClaimIceCandidatesResponse from a JSON string
claim_ice_candidates_response_instance = ClaimIceCandidatesResponse.from_json(json)
# print the JSON string representation of the object
print(ClaimIceCandidatesResponse.to_json())
# convert the object into a dict
claim_ice_candidates_response_dict = claim_ice_candidates_response_instance.to_dict()
# create an instance of ClaimIceCandidatesResponse from a dict
claim_ice_candidates_response_form_dict = claim_ice_candidates_response.from_dict(claim_ice_candidates_response_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,30 @@
# GoogleProtobufAny
Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**type** | **str** | The type of the serialized message. | [optional]
## Example
```python
from openapi_client.models.google_protobuf_any import GoogleProtobufAny
# TODO update the JSON string below
json = "{}"
# create an instance of GoogleProtobufAny from a JSON string
google_protobuf_any_instance = GoogleProtobufAny.from_json(json)
# print the JSON string representation of the object
print(GoogleProtobufAny.to_json())
# convert the object into a dict
google_protobuf_any_dict = google_protobuf_any_instance.to_dict()
# create an instance of GoogleProtobufAny from a dict
google_protobuf_any_form_dict = google_protobuf_any.from_dict(google_protobuf_any_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,33 @@
# IceCandidate
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**candidate** | **str** | | [optional]
**sdp_mid** | **str** | | [optional]
**sdp_line_index** | **int** | | [optional]
**username_fragment** | **str** | | [optional]
## Example
```python
from openapi_client.models.ice_candidate import IceCandidate
# TODO update the JSON string below
json = "{}"
# create an instance of IceCandidate from a JSON string
ice_candidate_instance = IceCandidate.from_json(json)
# print the JSON string representation of the object
print(IceCandidate.to_json())
# convert the object into a dict
ice_candidate_dict = ice_candidate_instance.to_dict()
# create an instance of IceCandidate from a dict
ice_candidate_form_dict = ice_candidate.from_dict(ice_candidate_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,31 @@
# IceSessionDescription
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | A unique identifier which can be used to send ICE candidates Maps to the session name | [optional]
**sdp_type** | **str** | Used to construct the remote description in WebRTC | [optional]
**sdp** | **str** | | [optional]
## Example
```python
from openapi_client.models.ice_session_description import IceSessionDescription
# TODO update the JSON string below
json = "{}"
# create an instance of IceSessionDescription from a JSON string
ice_session_description_instance = IceSessionDescription.from_json(json)
# print the JSON string representation of the object
print(IceSessionDescription.to_json())
# convert the object into a dict
ice_session_description_dict = ice_session_description_instance.to_dict()
# create an instance of IceSessionDescription from a dict
ice_session_description_form_dict = ice_session_description.from_dict(ice_session_description_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,31 @@
# Knock
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**offer** | [**IceSessionDescription**](IceSessionDescription.md) | The service being connected too | [optional]
**answer** | [**IceSessionDescription**](IceSessionDescription.md) | | [optional]
## Example
```python
from openapi_client.models.knock import Knock
# TODO update the JSON string below
json = "{}"
# create an instance of Knock from a JSON string
knock_instance = Knock.from_json(json)
# print the JSON string representation of the object
print(Knock.to_json())
# convert the object into a dict
knock_dict = knock_instance.to_dict()
# create an instance of Knock from a dict
knock_form_dict = knock.from_dict(knock_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,29 @@
# ListKnocksResponse
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**knocks** | [**List[Knock]**](Knock.md) | | [optional]
## Example
```python
from openapi_client.models.list_knocks_response import ListKnocksResponse
# TODO update the JSON string below
json = "{}"
# create an instance of ListKnocksResponse from a JSON string
list_knocks_response_instance = ListKnocksResponse.from_json(json)
# print the JSON string representation of the object
print(ListKnocksResponse.to_json())
# convert the object into a dict
list_knocks_response_dict = list_knocks_response_instance.to_dict()
# create an instance of ListKnocksResponse from a dict
list_knocks_response_form_dict = list_knocks_response.from_dict(list_knocks_response_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,765 @@
# openapi_client.PeerNetServiceApi
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**peer_net_service_claim_ice_candidates**](PeerNetServiceApi.md#peer_net_service_claim_ice_candidates) | **GET** /v1/sessions/{session}/claim/candidates |
[**peer_net_service_create_ice_candidate**](PeerNetServiceApi.md#peer_net_service_create_ice_candidate) | **POST** /v1/sessions/{session}/candidates |
[**peer_net_service_create_knock**](PeerNetServiceApi.md#peer_net_service_create_knock) | **POST** /v1/servers/{server}/services/{service}/knocks |
[**peer_net_service_create_server**](PeerNetServiceApi.md#peer_net_service_create_server) | **POST** /v1/servers |
[**peer_net_service_create_service**](PeerNetServiceApi.md#peer_net_service_create_service) | **POST** /v1/servers/{server}/services |
[**peer_net_service_delete_server**](PeerNetServiceApi.md#peer_net_service_delete_server) | **DELETE** /v1/servers/* |
[**peer_net_service_delete_service**](PeerNetServiceApi.md#peer_net_service_delete_service) | **DELETE** /v1/servers/{server}/services/{service} |
[**peer_net_service_get_knock**](PeerNetServiceApi.md#peer_net_service_get_knock) | **GET** /v1/servers/{server}/services/{service}/knocks/{knock} |
[**peer_net_service_get_room**](PeerNetServiceApi.md#peer_net_service_get_room) | **GET** /v1/rooms/{room} |
[**peer_net_service_list_knocks**](PeerNetServiceApi.md#peer_net_service_list_knocks) | **GET** /v1/servers/{server}/services/{service}/knocks |
[**peer_net_service_update_knock**](PeerNetServiceApi.md#peer_net_service_update_knock) | **PATCH** /v1/servers/{server}/services/{service}/knocks/{knock} |
# **peer_net_service_claim_ice_candidates**
> ClaimIceCandidatesResponse peer_net_service_claim_ice_candidates(session)
Acts as both List and Delete atomically.
### Example
```python
import openapi_client
from openapi_client.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
session = 'session_example' # str | The session id.
try:
api_response = api_instance.peer_net_service_claim_ice_candidates(session)
print("The response of PeerNetServiceApi->peer_net_service_claim_ice_candidates:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_claim_ice_candidates: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**session** | **str**| The session id. |
### Return type
[**ClaimIceCandidatesResponse**](ClaimIceCandidatesResponse.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_create_ice_candidate**
> IceCandidate peer_net_service_create_ice_candidate(session, ice_candidate)
### Example
```python
import openapi_client
from openapi_client.models.ice_candidate import IceCandidate
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
session = 'session_example' # str | The session id.
ice_candidate = openapi_client.IceCandidate() # IceCandidate |
try:
api_response = api_instance.peer_net_service_create_ice_candidate(session, ice_candidate)
print("The response of PeerNetServiceApi->peer_net_service_create_ice_candidate:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_create_ice_candidate: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**session** | **str**| The session id. |
**ice_candidate** | [**IceCandidate**](IceCandidate.md)| |
### Return type
[**IceCandidate**](IceCandidate.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_create_knock**
> Knock peer_net_service_create_knock(server, service, knock)
Creates a knock that will be answered by the peer; the signaler may delete the knock, regardless of the state, when it ages.
### Example
```python
import openapi_client
from openapi_client.models.knock import Knock
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = 'service_example' # str | The service id.
knock = openapi_client.Knock() # Knock |
try:
api_response = api_instance.peer_net_service_create_knock(server, service, knock)
print("The response of PeerNetServiceApi->peer_net_service_create_knock:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_create_knock: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | **str**| The service id. |
**knock** | [**Knock**](Knock.md)| |
### Return type
[**Knock**](Knock.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_create_server**
> Server peer_net_service_create_server(server)
### Example
```python
import openapi_client
from openapi_client.models.server import Server
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = openapi_client.Server() # Server |
try:
api_response = api_instance.peer_net_service_create_server(server)
print("The response of PeerNetServiceApi->peer_net_service_create_server:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_create_server: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | [**Server**](Server.md)| |
### Return type
[**Server**](Server.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_create_service**
> Service peer_net_service_create_service(server, service)
### Example
```python
import openapi_client
from openapi_client.models.service import Service
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = openapi_client.Service() # Service |
try:
api_response = api_instance.peer_net_service_create_service(server, service)
print("The response of PeerNetServiceApi->peer_net_service_create_service:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_create_service: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | [**Service**](Service.md)| |
### Return type
[**Service**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_delete_server**
> peer_net_service_delete_server(name=name)
### Example
```python
import openapi_client
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
name = 'name_example' # str | (optional)
try:
api_instance.peer_net_service_delete_server(name=name)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_delete_server: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**name** | **str**| | [optional]
### Return type
void (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_delete_service**
> peer_net_service_delete_service(server, service)
### Example
```python
import openapi_client
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = 'service_example' # str | The service id.
try:
api_instance.peer_net_service_delete_service(server, service)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_delete_service: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | **str**| The service id. |
### Return type
void (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_get_knock**
> Knock peer_net_service_get_knock(server, service, knock)
### Example
```python
import openapi_client
from openapi_client.models.knock import Knock
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = 'service_example' # str | The service id.
knock = 'knock_example' # str | The knock id.
try:
api_response = api_instance.peer_net_service_get_knock(server, service, knock)
print("The response of PeerNetServiceApi->peer_net_service_get_knock:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_get_knock: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | **str**| The service id. |
**knock** | **str**| The knock id. |
### Return type
[**Knock**](Knock.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_get_room**
> Room peer_net_service_get_room(room)
### Example
```python
import openapi_client
from openapi_client.models.room import Room
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
room = 'room_example' # str | The room id.
try:
api_response = api_instance.peer_net_service_get_room(room)
print("The response of PeerNetServiceApi->peer_net_service_get_room:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_get_room: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**room** | **str**| The room id. |
### Return type
[**Room**](Room.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_list_knocks**
> ListKnocksResponse peer_net_service_list_knocks(server, service)
### Example
```python
import openapi_client
from openapi_client.models.list_knocks_response import ListKnocksResponse
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = 'service_example' # str | The service id.
try:
api_response = api_instance.peer_net_service_list_knocks(server, service)
print("The response of PeerNetServiceApi->peer_net_service_list_knocks:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_list_knocks: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | **str**| The service id. |
### Return type
[**ListKnocksResponse**](ListKnocksResponse.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **peer_net_service_update_knock**
> Knock peer_net_service_update_knock(server, service, knock, knock2)
### Example
```python
import openapi_client
from openapi_client.models.knock import Knock
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.PeerNetServiceApi(api_client)
server = 'server_example' # str | The server id.
service = 'service_example' # str | The service id.
knock = 'knock_example' # str | The knock id.
knock2 = openapi_client.Knock() # Knock |
try:
api_response = api_instance.peer_net_service_update_knock(server, service, knock, knock2)
print("The response of PeerNetServiceApi->peer_net_service_update_knock:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling PeerNetServiceApi->peer_net_service_update_knock: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**server** | **str**| The server id. |
**service** | **str**| The service id. |
**knock** | **str**| The knock id. |
**knock2** | [**Knock**](Knock.md)| |
### Return type
[**Knock**](Knock.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | OK | - |
**0** | Default error response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -0,0 +1,31 @@
# Room
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**display_name** | **str** | | [optional]
**servers** | [**List[Server]**](Server.md) | | [optional]
## Example
```python
from openapi_client.models.room import Room
# TODO update the JSON string below
json = "{}"
# create an instance of Room from a JSON string
room_instance = Room.from_json(json)
# print the JSON string representation of the object
print(Room.to_json())
# convert the object into a dict
room_dict = room_instance.to_dict()
# create an instance of Room from a dict
room_form_dict = room.from_dict(room_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,33 @@
# Server
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**rooms** | **List[str]** | Tracks which rooms the server should be listed in; this will not be set when a room is listed to preserve privacy of servers. | [optional]
**auth_token** | **str** | Used to authenticate requests which access knocks for this server or attempt to update, delete or create services. In future calls, add a header with the format: Authorization: Bearer &lt;auth_token&gt; | [optional]
**display_name** | **str** | | [optional]
**services** | [**List[Service]**](Service.md) | | [optional]
## Example
```python
from openapi_client.models.server import Server
# TODO update the JSON string below
json = "{}"
# create an instance of Server from a JSON string
server_instance = Server.from_json(json)
# print the JSON string representation of the object
print(Server.to_json())
# convert the object into a dict
server_dict = server_instance.to_dict()
# create an instance of Server from a dict
server_form_dict = server.from_dict(server_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,31 @@
# Service
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**protocol** | **str** | | [optional]
**version** | **str** | | [optional]
## Example
```python
from openapi_client.models.service import Service
# TODO update the JSON string below
json = "{}"
# create an instance of Service from a JSON string
service_instance = Service.from_json(json)
# print the JSON string representation of the object
print(Service.to_json())
# convert the object into a dict
service_dict = service_instance.to_dict()
# create an instance of Service from a dict
service_form_dict = service.from_dict(service_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,32 @@
# Status
The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**code** | **int** | The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. | [optional]
**message** | **str** | A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. | [optional]
**details** | [**List[GoogleProtobufAny]**](GoogleProtobufAny.md) | A list of messages that carry the error details. There is a common set of message types for APIs to use. | [optional]
## Example
```python
from openapi_client.models.status import Status
# TODO update the JSON string below
json = "{}"
# create an instance of Status from a JSON string
status_instance = Status.from_json(json)
# print the JSON string representation of the object
print(Status.to_json())
# convert the object into a dict
status_dict = status_instance.to_dict()
# create an instance of Status from a dict
status_form_dict = status.from_dict(status_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,57 @@
#!/bin/sh
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
#
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
git_user_id=$1
git_repo_id=$2
release_note=$3
git_host=$4
if [ "$git_host" = "" ]; then
git_host="github.com"
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
fi
if [ "$git_user_id" = "" ]; then
git_user_id="GIT_USER_ID"
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
fi
if [ "$git_repo_id" = "" ]; then
git_repo_id="GIT_REPO_ID"
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
fi
if [ "$release_note" = "" ]; then
release_note="Minor update"
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
fi
# Initialize the local directory as a Git repository
git init
# Adds the files in the local repository and stages them for commit.
git add .
# Commits the tracked changes and prepares them to be pushed to a remote repository.
git commit -m "$release_note"
# Sets the new remote
git_remote=$(git remote)
if [ "$git_remote" = "" ]; then # git remote not defined
if [ "$GIT_TOKEN" = "" ]; then
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
else
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
fi
fi
git pull origin master
# Pushes (Forces) the changes in the local repository up to the remote repository
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
git push origin master 2>&1 | grep -v 'To https'

View File

@@ -0,0 +1,43 @@
# coding: utf-8
# flake8: noqa
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
__version__ = "1.0.0"
# import apis into sdk package
from openapi_client.api.peer_net_service_api import PeerNetServiceApi
# import ApiClient
from openapi_client.api_response import ApiResponse
from openapi_client.api_client import ApiClient
from openapi_client.configuration import Configuration
from openapi_client.exceptions import OpenApiException
from openapi_client.exceptions import ApiTypeError
from openapi_client.exceptions import ApiValueError
from openapi_client.exceptions import ApiKeyError
from openapi_client.exceptions import ApiAttributeError
from openapi_client.exceptions import ApiException
# import models into sdk package
from openapi_client.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
from openapi_client.models.google_protobuf_any import GoogleProtobufAny
from openapi_client.models.ice_candidate import IceCandidate
from openapi_client.models.ice_session_description import IceSessionDescription
from openapi_client.models.knock import Knock
from openapi_client.models.list_knocks_response import ListKnocksResponse
from openapi_client.models.room import Room
from openapi_client.models.server import Server
from openapi_client.models.service import Service
from openapi_client.models.status import Status

View File

@@ -0,0 +1,5 @@
# flake8: noqa
# import apis into api package
from openapi_client.api.peer_net_service_api import PeerNetServiceApi

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,758 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import datetime
from dateutil.parser import parse
from enum import Enum
import json
import mimetypes
import os
import re
import tempfile
from urllib.parse import quote
from typing import Tuple, Optional, List, Dict
from openapi_client.configuration import Configuration
from openapi_client.api_response import ApiResponse, T as ApiResponseT
import openapi_client.models
from openapi_client import rest
from openapi_client.exceptions import (
ApiValueError,
ApiException,
BadRequestException,
UnauthorizedException,
ForbiddenException,
NotFoundException,
ServiceException
)
RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
class ApiClient:
"""Generic API client for OpenAPI client library builds.
OpenAPI generic API client. This client handles the client-
server communication, and is invariant across implementations. Specifics of
the methods and models for each application are generated from the OpenAPI
templates.
:param configuration: .Configuration object for this client
:param header_name: a header to pass when making calls to the API.
:param header_value: a header value to pass when making calls to
the API.
:param cookie: a cookie to include in the header when making calls
to the API
"""
PRIMITIVE_TYPES = (float, bool, bytes, str, int)
NATIVE_TYPES_MAPPING = {
'int': int,
'long': int, # TODO remove as only py3 is supported?
'float': float,
'str': str,
'bool': bool,
'date': datetime.date,
'datetime': datetime.datetime,
'object': object,
}
_pool = None
def __init__(
self,
configuration=None,
header_name=None,
header_value=None,
cookie=None
) -> None:
# use default configuration if none is provided
if configuration is None:
configuration = Configuration.get_default()
self.configuration = configuration
self.rest_client = rest.RESTClientObject(configuration)
self.default_headers = {}
if header_name is not None:
self.default_headers[header_name] = header_value
self.cookie = cookie
# Set default User-Agent.
self.user_agent = 'OpenAPI-Generator/1.0.0/python'
self.client_side_validation = configuration.client_side_validation
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
@property
def user_agent(self):
"""User agent for this API client"""
return self.default_headers['User-Agent']
@user_agent.setter
def user_agent(self, value):
self.default_headers['User-Agent'] = value
def set_default_header(self, header_name, header_value):
self.default_headers[header_name] = header_value
_default = None
@classmethod
def get_default(cls):
"""Return new instance of ApiClient.
This method returns newly created, based on default constructor,
object of ApiClient class or returns a copy of default
ApiClient.
:return: The ApiClient object.
"""
if cls._default is None:
cls._default = ApiClient()
return cls._default
@classmethod
def set_default(cls, default):
"""Set default instance of ApiClient.
It stores default ApiClient.
:param default: object of ApiClient.
"""
cls._default = default
def param_serialize(
self,
method,
resource_path,
path_params=None,
query_params=None,
header_params=None,
body=None,
post_params=None,
files=None, auth_settings=None,
collection_formats=None,
_host=None,
_request_auth=None
) -> RequestSerialized:
"""Builds the HTTP request params needed by the request.
:param method: Method to call.
:param resource_path: Path to method endpoint.
:param path_params: Path parameters in the url.
:param query_params: Query parameters in the url.
:param header_params: Header parameters to be
placed in the request header.
:param body: Request body.
:param post_params dict: Request post form parameters,
for `application/x-www-form-urlencoded`, `multipart/form-data`.
:param auth_settings list: Auth Settings names for the request.
:param files dict: key -> filename, value -> filepath,
for `multipart/form-data`.
:param collection_formats: dict of collection formats for path, query,
header, and post parameters.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:return: tuple of form (path, http_method, query_params, header_params,
body, post_params, files)
"""
config = self.configuration
# header parameters
header_params = header_params or {}
header_params.update(self.default_headers)
if self.cookie:
header_params['Cookie'] = self.cookie
if header_params:
header_params = self.sanitize_for_serialization(header_params)
header_params = dict(
self.parameters_to_tuples(header_params,collection_formats)
)
# path parameters
if path_params:
path_params = self.sanitize_for_serialization(path_params)
path_params = self.parameters_to_tuples(
path_params,
collection_formats
)
for k, v in path_params:
# specified safe chars, encode everything
resource_path = resource_path.replace(
'{%s}' % k,
quote(str(v), safe=config.safe_chars_for_path_param)
)
# post parameters
if post_params or files:
post_params = post_params if post_params else []
post_params = self.sanitize_for_serialization(post_params)
post_params = self.parameters_to_tuples(
post_params,
collection_formats
)
post_params.extend(self.files_parameters(files))
# auth setting
self.update_params_for_auth(
header_params,
query_params,
auth_settings,
resource_path,
method,
body,
request_auth=_request_auth
)
# body
if body:
body = self.sanitize_for_serialization(body)
# request url
if _host is None:
url = self.configuration.host + resource_path
else:
# use server/host defined in path or operation instead
url = _host + resource_path
# query parameters
if query_params:
query_params = self.sanitize_for_serialization(query_params)
url_query = self.parameters_to_url_query(
query_params,
collection_formats
)
url += "?" + url_query
return method, url, header_params, body, post_params
def call_api(
self,
method,
url,
header_params=None,
body=None,
post_params=None,
_request_timeout=None
) -> rest.RESTResponse:
"""Makes the HTTP request (synchronous)
:param method: Method to call.
:param url: Path to method endpoint.
:param header_params: Header parameters to be
placed in the request header.
:param body: Request body.
:param post_params dict: Request post form parameters,
for `application/x-www-form-urlencoded`, `multipart/form-data`.
:param _request_timeout: timeout setting for this request.
:return: RESTResponse
"""
try:
# perform request and return response
response_data = self.rest_client.request(
method, url,
headers=header_params,
body=body, post_params=post_params,
_request_timeout=_request_timeout
)
except ApiException as e:
raise e
return response_data
def response_deserialize(
self,
response_data: rest.RESTResponse,
response_types_map: Optional[Dict[str, ApiResponseT]]=None
) -> ApiResponse[ApiResponseT]:
"""Deserializes response into an object.
:param response_data: RESTResponse object to be deserialized.
:param response_types_map: dict of response types.
:return: ApiResponse
"""
msg = "RESTResponse.read() must be called before passing it to response_deserialize()"
assert response_data.data is not None, msg
response_type = response_types_map.get(str(response_data.status), None)
if not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599:
# if not found, look for '1XX', '2XX', etc.
response_type = response_types_map.get(str(response_data.status)[0] + "XX", None)
# deserialize response data
response_text = None
return_data = None
try:
if response_type == "bytearray":
return_data = response_data.data
elif response_type == "file":
return_data = self.__deserialize_file(response_data)
elif response_type is not None:
match = None
content_type = response_data.getheader('content-type')
if content_type is not None:
match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
encoding = match.group(1) if match else "utf-8"
response_text = response_data.data.decode(encoding)
return_data = self.deserialize(response_text, response_type)
finally:
if not 200 <= response_data.status <= 299:
raise ApiException.from_response(
http_resp=response_data,
body=response_text,
data=return_data,
)
return ApiResponse(
status_code = response_data.status,
data = return_data,
headers = response_data.getheaders(),
raw_data = response_data.data
)
def sanitize_for_serialization(self, obj):
"""Builds a JSON POST object.
If obj is None, return None.
If obj is str, int, long, float, bool, return directly.
If obj is datetime.datetime, datetime.date
convert to string in iso8601 format.
If obj is list, sanitize each element in the list.
If obj is dict, return the dict.
If obj is OpenAPI model, return the properties dict.
:param obj: The data to serialize.
:return: The serialized form of data.
"""
if obj is None:
return None
elif isinstance(obj, self.PRIMITIVE_TYPES):
return obj
elif isinstance(obj, list):
return [
self.sanitize_for_serialization(sub_obj) for sub_obj in obj
]
elif isinstance(obj, tuple):
return tuple(
self.sanitize_for_serialization(sub_obj) for sub_obj in obj
)
elif isinstance(obj, (datetime.datetime, datetime.date)):
return obj.isoformat()
elif isinstance(obj, dict):
obj_dict = obj
else:
# Convert model obj to dict except
# attributes `openapi_types`, `attribute_map`
# and attributes which value is not None.
# Convert attribute name to json key in
# model definition for request.
obj_dict = obj.to_dict()
return {
key: self.sanitize_for_serialization(val)
for key, val in obj_dict.items()
}
def deserialize(self, response_text, response_type):
"""Deserializes response into an object.
:param response: RESTResponse object to be deserialized.
:param response_type: class literal for
deserialized object, or string of class name.
:return: deserialized object.
"""
# fetch data from response object
try:
data = json.loads(response_text)
except ValueError:
data = response_text
return self.__deserialize(data, response_type)
def __deserialize(self, data, klass):
"""Deserializes dict, list, str into an object.
:param data: dict, list or str.
:param klass: class literal, or string of class name.
:return: object.
"""
if data is None:
return None
if isinstance(klass, str):
if klass.startswith('List['):
m = re.match(r'List\[(.*)]', klass)
assert m is not None, "Malformed List type definition"
sub_kls = m.group(1)
return [self.__deserialize(sub_data, sub_kls)
for sub_data in data]
if klass.startswith('Dict['):
m = re.match(r'Dict\[([^,]*), (.*)]', klass)
assert m is not None, "Malformed Dict type definition"
sub_kls = m.group(2)
return {k: self.__deserialize(v, sub_kls)
for k, v in data.items()}
# convert str to class
if klass in self.NATIVE_TYPES_MAPPING:
klass = self.NATIVE_TYPES_MAPPING[klass]
else:
klass = getattr(openapi_client.models, klass)
if klass in self.PRIMITIVE_TYPES:
return self.__deserialize_primitive(data, klass)
elif klass == object:
return self.__deserialize_object(data)
elif klass == datetime.date:
return self.__deserialize_date(data)
elif klass == datetime.datetime:
return self.__deserialize_datetime(data)
elif issubclass(klass, Enum):
return self.__deserialize_enum(data, klass)
else:
return self.__deserialize_model(data, klass)
def parameters_to_tuples(self, params, collection_formats):
"""Get parameters as list of tuples, formatting collections.
:param params: Parameters as dict or list of two-tuples
:param dict collection_formats: Parameter collection formats
:return: Parameters as list of tuples, collections formatted
"""
new_params: List[Tuple[str, str]] = []
if collection_formats is None:
collection_formats = {}
for k, v in params.items() if isinstance(params, dict) else params:
if k in collection_formats:
collection_format = collection_formats[k]
if collection_format == 'multi':
new_params.extend((k, value) for value in v)
else:
if collection_format == 'ssv':
delimiter = ' '
elif collection_format == 'tsv':
delimiter = '\t'
elif collection_format == 'pipes':
delimiter = '|'
else: # csv is the default
delimiter = ','
new_params.append(
(k, delimiter.join(str(value) for value in v)))
else:
new_params.append((k, v))
return new_params
def parameters_to_url_query(self, params, collection_formats):
"""Get parameters as list of tuples, formatting collections.
:param params: Parameters as dict or list of two-tuples
:param dict collection_formats: Parameter collection formats
:return: URL query string (e.g. a=Hello%20World&b=123)
"""
new_params: List[Tuple[str, str]] = []
if collection_formats is None:
collection_formats = {}
for k, v in params.items() if isinstance(params, dict) else params:
if isinstance(v, bool):
v = str(v).lower()
if isinstance(v, (int, float)):
v = str(v)
if isinstance(v, dict):
v = json.dumps(v)
if k in collection_formats:
collection_format = collection_formats[k]
if collection_format == 'multi':
new_params.extend((k, str(value)) for value in v)
else:
if collection_format == 'ssv':
delimiter = ' '
elif collection_format == 'tsv':
delimiter = '\t'
elif collection_format == 'pipes':
delimiter = '|'
else: # csv is the default
delimiter = ','
new_params.append(
(k, delimiter.join(quote(str(value)) for value in v))
)
else:
new_params.append((k, quote(str(v))))
return "&".join(["=".join(map(str, item)) for item in new_params])
def files_parameters(self, files=None):
"""Builds form parameters.
:param files: File parameters.
:return: Form parameters with files.
"""
params = []
if files:
for k, v in files.items():
if not v:
continue
file_names = v if type(v) is list else [v]
for n in file_names:
with open(n, 'rb') as f:
filename = os.path.basename(f.name)
filedata = f.read()
mimetype = (
mimetypes.guess_type(filename)[0]
or 'application/octet-stream'
)
params.append(
tuple([k, tuple([filename, filedata, mimetype])])
)
return params
def select_header_accept(self, accepts: List[str]) -> Optional[str]:
"""Returns `Accept` based on an array of accepts provided.
:param accepts: List of headers.
:return: Accept (e.g. application/json).
"""
if not accepts:
return None
for accept in accepts:
if re.search('json', accept, re.IGNORECASE):
return accept
return accepts[0]
def select_header_content_type(self, content_types):
"""Returns `Content-Type` based on an array of content_types provided.
:param content_types: List of content-types.
:return: Content-Type (e.g. application/json).
"""
if not content_types:
return None
for content_type in content_types:
if re.search('json', content_type, re.IGNORECASE):
return content_type
return content_types[0]
def update_params_for_auth(
self,
headers,
queries,
auth_settings,
resource_path,
method,
body,
request_auth=None
) -> None:
"""Updates header and query params based on authentication setting.
:param headers: Header parameters dict to be updated.
:param queries: Query parameters tuple list to be updated.
:param auth_settings: Authentication setting identifiers list.
:resource_path: A string representation of the HTTP request resource path.
:method: A string representation of the HTTP request method.
:body: A object representing the body of the HTTP request.
The object type is the return value of sanitize_for_serialization().
:param request_auth: if set, the provided settings will
override the token in the configuration.
"""
if not auth_settings:
return
if request_auth:
self._apply_auth_params(
headers,
queries,
resource_path,
method,
body,
request_auth
)
else:
for auth in auth_settings:
auth_setting = self.configuration.auth_settings().get(auth)
if auth_setting:
self._apply_auth_params(
headers,
queries,
resource_path,
method,
body,
auth_setting
)
def _apply_auth_params(
self,
headers,
queries,
resource_path,
method,
body,
auth_setting
) -> None:
"""Updates the request parameters based on a single auth_setting
:param headers: Header parameters dict to be updated.
:param queries: Query parameters tuple list to be updated.
:resource_path: A string representation of the HTTP request resource path.
:method: A string representation of the HTTP request method.
:body: A object representing the body of the HTTP request.
The object type is the return value of sanitize_for_serialization().
:param auth_setting: auth settings for the endpoint
"""
if auth_setting['in'] == 'cookie':
headers['Cookie'] = auth_setting['value']
elif auth_setting['in'] == 'header':
if auth_setting['type'] != 'http-signature':
headers[auth_setting['key']] = auth_setting['value']
elif auth_setting['in'] == 'query':
queries.append((auth_setting['key'], auth_setting['value']))
else:
raise ApiValueError(
'Authentication token must be in `query` or `header`'
)
def __deserialize_file(self, response):
"""Deserializes body to file
Saves response body into a file in a temporary folder,
using the filename from the `Content-Disposition` header if provided.
handle file downloading
save response body into a tmp file and return the instance
:param response: RESTResponse.
:return: file path.
"""
fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
os.close(fd)
os.remove(path)
content_disposition = response.getheader("Content-Disposition")
if content_disposition:
m = re.search(
r'filename=[\'"]?([^\'"\s]+)[\'"]?',
content_disposition
)
assert m is not None, "Unexpected 'content-disposition' header value"
filename = m.group(1)
path = os.path.join(os.path.dirname(path), filename)
with open(path, "wb") as f:
f.write(response.data)
return path
def __deserialize_primitive(self, data, klass):
"""Deserializes string to primitive type.
:param data: str.
:param klass: class literal.
:return: int, long, float, str, bool.
"""
try:
return klass(data)
except UnicodeEncodeError:
return str(data)
except TypeError:
return data
def __deserialize_object(self, value):
"""Return an original value.
:return: object.
"""
return value
def __deserialize_date(self, string):
"""Deserializes string to date.
:param string: str.
:return: date.
"""
try:
return parse(string).date()
except ImportError:
return string
except ValueError:
raise rest.ApiException(
status=0,
reason="Failed to parse `{0}` as date object".format(string)
)
def __deserialize_datetime(self, string):
"""Deserializes string to datetime.
The string should be in iso8601 datetime format.
:param string: str.
:return: datetime.
"""
try:
return parse(string)
except ImportError:
return string
except ValueError:
raise rest.ApiException(
status=0,
reason=(
"Failed to parse `{0}` as datetime object"
.format(string)
)
)
def __deserialize_enum(self, data, klass):
"""Deserializes primitive type to enum.
:param data: primitive type.
:param klass: class literal.
:return: enum value.
"""
try:
return klass(data)
except ValueError:
raise rest.ApiException(
status=0,
reason=(
"Failed to parse `{0}` as `{1}`"
.format(data, klass)
)
)
def __deserialize_model(self, data, klass):
"""Deserializes list or dict to model.
:param data: dict, list.
:param klass: class literal.
:return: model object.
"""
return klass.from_dict(data)

View File

@@ -0,0 +1,21 @@
"""API response object."""
from __future__ import annotations
from typing import Optional, Generic, Mapping, TypeVar
from pydantic import Field, StrictInt, StrictBytes, BaseModel
T = TypeVar("T")
class ApiResponse(BaseModel, Generic[T]):
"""
API response object
"""
status_code: StrictInt = Field(description="HTTP status code")
headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers")
data: T = Field(description="Deserialized data given the data type")
raw_data: StrictBytes = Field(description="Raw data (HTTP response body)")
model_config = {
"arbitrary_types_allowed": True
}

View File

@@ -0,0 +1,436 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import copy
import logging
from logging import FileHandler
import multiprocessing
import sys
from typing import Optional
import urllib3
import http.client as httplib
JSON_SCHEMA_VALIDATION_KEYWORDS = {
'multipleOf', 'maximum', 'exclusiveMaximum',
'minimum', 'exclusiveMinimum', 'maxLength',
'minLength', 'pattern', 'maxItems', 'minItems'
}
class Configuration:
"""This class contains various settings of the API client.
:param host: Base url.
:param api_key: Dict to store API key(s).
Each entry in the dict specifies an API key.
The dict key is the name of the security scheme in the OAS specification.
The dict value is the API key secret.
:param api_key_prefix: Dict to store API prefix (e.g. Bearer).
The dict key is the name of the security scheme in the OAS specification.
The dict value is an API key prefix when generating the auth data.
:param username: Username for HTTP basic authentication.
:param password: Password for HTTP basic authentication.
:param access_token: Access token.
:param server_index: Index to servers configuration.
:param server_variables: Mapping with string values to replace variables in
templated server configuration. The validation of enums is performed for
variables with defined enum values before.
:param server_operation_index: Mapping from operation ID to an index to server
configuration.
:param server_operation_variables: Mapping from operation ID to a mapping with
string values to replace variables in templated server configuration.
The validation of enums is performed for variables with defined enum
values before.
:param ssl_ca_cert: str - the path to a file of concatenated CA certificates
in PEM format.
"""
_default = None
def __init__(self, host=None,
api_key=None, api_key_prefix=None,
username=None, password=None,
access_token=None,
server_index=None, server_variables=None,
server_operation_index=None, server_operation_variables=None,
ssl_ca_cert=None,
) -> None:
"""Constructor
"""
self._base_path = "http://localhost" if host is None else host
"""Default Base url
"""
self.server_index = 0 if server_index is None and host is None else server_index
self.server_operation_index = server_operation_index or {}
"""Default server index
"""
self.server_variables = server_variables or {}
self.server_operation_variables = server_operation_variables or {}
"""Default server variables
"""
self.temp_folder_path = None
"""Temp file folder for downloading files
"""
# Authentication Settings
self.api_key = {}
if api_key:
self.api_key = api_key
"""dict to store API key(s)
"""
self.api_key_prefix = {}
if api_key_prefix:
self.api_key_prefix = api_key_prefix
"""dict to store API prefix (e.g. Bearer)
"""
self.refresh_api_key_hook = None
"""function hook to refresh API key if expired
"""
self.username = username
"""Username for HTTP basic authentication
"""
self.password = password
"""Password for HTTP basic authentication
"""
self.access_token = access_token
"""Access token
"""
self.logger = {}
"""Logging Settings
"""
self.logger["package_logger"] = logging.getLogger("openapi_client")
self.logger["urllib3_logger"] = logging.getLogger("urllib3")
self.logger_format = '%(asctime)s %(levelname)s %(message)s'
"""Log format
"""
self.logger_stream_handler = None
"""Log stream handler
"""
self.logger_file_handler: Optional[FileHandler] = None
"""Log file handler
"""
self.logger_file = None
"""Debug file location
"""
self.debug = False
"""Debug switch
"""
self.verify_ssl = True
"""SSL/TLS verification
Set this to false to skip verifying SSL certificate when calling API
from https server.
"""
self.ssl_ca_cert = ssl_ca_cert
"""Set this to customize the certificate file to verify the peer.
"""
self.cert_file = None
"""client certificate file
"""
self.key_file = None
"""client key file
"""
self.assert_hostname = None
"""Set this to True/False to enable/disable SSL hostname verification.
"""
self.tls_server_name = None
"""SSL/TLS Server Name Indication (SNI)
Set this to the SNI value expected by the server.
"""
self.connection_pool_maxsize = multiprocessing.cpu_count() * 5
"""urllib3 connection pool's maximum number of connections saved
per pool. urllib3 uses 1 connection as default value, but this is
not the best value when you are making a lot of possibly parallel
requests to the same host, which is often the case here.
cpu_count * 5 is used as default value to increase performance.
"""
self.proxy: Optional[str] = None
"""Proxy URL
"""
self.proxy_headers = None
"""Proxy headers
"""
self.safe_chars_for_path_param = ''
"""Safe chars for path_param
"""
self.retries = None
"""Adding retries to override urllib3 default value 3
"""
# Enable client side validation
self.client_side_validation = True
self.socket_options = None
"""Options to pass down to the underlying urllib3 socket
"""
self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z"
"""datetime format
"""
self.date_format = "%Y-%m-%d"
"""date format
"""
def __deepcopy__(self, memo):
cls = self.__class__
result = cls.__new__(cls)
memo[id(self)] = result
for k, v in self.__dict__.items():
if k not in ('logger', 'logger_file_handler'):
setattr(result, k, copy.deepcopy(v, memo))
# shallow copy of loggers
result.logger = copy.copy(self.logger)
# use setters to configure loggers
result.logger_file = self.logger_file
result.debug = self.debug
return result
def __setattr__(self, name, value):
object.__setattr__(self, name, value)
@classmethod
def set_default(cls, default):
"""Set default instance of configuration.
It stores default configuration, which can be
returned by get_default_copy method.
:param default: object of Configuration
"""
cls._default = default
@classmethod
def get_default_copy(cls):
"""Deprecated. Please use `get_default` instead.
Deprecated. Please use `get_default` instead.
:return: The configuration object.
"""
return cls.get_default()
@classmethod
def get_default(cls):
"""Return the default configuration.
This method returns newly created, based on default constructor,
object of Configuration class or returns a copy of default
configuration.
:return: The configuration object.
"""
if cls._default is None:
cls._default = Configuration()
return cls._default
@property
def logger_file(self):
"""The logger file.
If the logger_file is None, then add stream handler and remove file
handler. Otherwise, add file handler and remove stream handler.
:param value: The logger_file path.
:type: str
"""
return self.__logger_file
@logger_file.setter
def logger_file(self, value):
"""The logger file.
If the logger_file is None, then add stream handler and remove file
handler. Otherwise, add file handler and remove stream handler.
:param value: The logger_file path.
:type: str
"""
self.__logger_file = value
if self.__logger_file:
# If set logging file,
# then add file handler and remove stream handler.
self.logger_file_handler = logging.FileHandler(self.__logger_file)
self.logger_file_handler.setFormatter(self.logger_formatter)
for _, logger in self.logger.items():
logger.addHandler(self.logger_file_handler)
@property
def debug(self):
"""Debug status
:param value: The debug status, True or False.
:type: bool
"""
return self.__debug
@debug.setter
def debug(self, value):
"""Debug status
:param value: The debug status, True or False.
:type: bool
"""
self.__debug = value
if self.__debug:
# if debug status is True, turn on debug logging
for _, logger in self.logger.items():
logger.setLevel(logging.DEBUG)
# turn on httplib debug
httplib.HTTPConnection.debuglevel = 1
else:
# if debug status is False, turn off debug logging,
# setting log level to default `logging.WARNING`
for _, logger in self.logger.items():
logger.setLevel(logging.WARNING)
# turn off httplib debug
httplib.HTTPConnection.debuglevel = 0
@property
def logger_format(self):
"""The logger format.
The logger_formatter will be updated when sets logger_format.
:param value: The format string.
:type: str
"""
return self.__logger_format
@logger_format.setter
def logger_format(self, value):
"""The logger format.
The logger_formatter will be updated when sets logger_format.
:param value: The format string.
:type: str
"""
self.__logger_format = value
self.logger_formatter = logging.Formatter(self.__logger_format)
def get_api_key_with_prefix(self, identifier, alias=None):
"""Gets API key (with prefix if set).
:param identifier: The identifier of apiKey.
:param alias: The alternative identifier of apiKey.
:return: The token for api key authentication.
"""
if self.refresh_api_key_hook is not None:
self.refresh_api_key_hook(self)
key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None)
if key:
prefix = self.api_key_prefix.get(identifier)
if prefix:
return "%s %s" % (prefix, key)
else:
return key
def get_basic_auth_token(self):
"""Gets HTTP basic authentication header (string).
:return: The token for basic HTTP authentication.
"""
username = ""
if self.username is not None:
username = self.username
password = ""
if self.password is not None:
password = self.password
return urllib3.util.make_headers(
basic_auth=username + ':' + password
).get('authorization')
def auth_settings(self):
"""Gets Auth Settings dict for api client.
:return: The Auth Settings information dict.
"""
auth = {}
return auth
def to_debug_report(self):
"""Gets the essential information for debugging.
:return: The report for debugging.
"""
return "Python SDK Debug Report:\n"\
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: 0.0.1\n"\
"SDK Package Version: 1.0.0".\
format(env=sys.platform, pyversion=sys.version)
def get_host_settings(self):
"""Gets an array of host settings
:return: An array of host settings
"""
return [
{
'url': "",
'description': "No description provided",
}
]
def get_host_from_settings(self, index, variables=None, servers=None):
"""Gets host URL based on the index and variables
:param index: array index of the host settings
:param variables: hash of variable and the corresponding value
:param servers: an array of host settings or None
:return: URL based on host settings
"""
if index is None:
return self._base_path
variables = {} if variables is None else variables
servers = self.get_host_settings() if servers is None else servers
try:
server = servers[index]
except IndexError:
raise ValueError(
"Invalid index {0} when selecting the host settings. "
"Must be less than {1}".format(index, len(servers)))
url = server['url']
# go through variables and replace placeholders
for variable_name, variable in server.get('variables', {}).items():
used_value = variables.get(
variable_name, variable['default_value'])
if 'enum_values' in variable \
and used_value not in variable['enum_values']:
raise ValueError(
"The variable `{0}` in the host URL has invalid value "
"{1}. Must be {2}.".format(
variable_name, variables[variable_name],
variable['enum_values']))
url = url.replace("{" + variable_name + "}", used_value)
return url
@property
def host(self):
"""Return generated host."""
return self.get_host_from_settings(self.server_index, variables=self.server_variables)
@host.setter
def host(self, value):
"""Fix base path."""
self._base_path = value
self.server_index = None

View File

@@ -0,0 +1,199 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from typing import Any, Optional
from typing_extensions import Self
class OpenApiException(Exception):
"""The base exception class for all OpenAPIExceptions"""
class ApiTypeError(OpenApiException, TypeError):
def __init__(self, msg, path_to_item=None, valid_classes=None,
key_type=None) -> None:
""" Raises an exception for TypeErrors
Args:
msg (str): the exception message
Keyword Args:
path_to_item (list): a list of keys an indices to get to the
current_item
None if unset
valid_classes (tuple): the primitive classes that current item
should be an instance of
None if unset
key_type (bool): False if our value is a value in a dict
True if it is a key in a dict
False if our item is an item in a list
None if unset
"""
self.path_to_item = path_to_item
self.valid_classes = valid_classes
self.key_type = key_type
full_msg = msg
if path_to_item:
full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
super(ApiTypeError, self).__init__(full_msg)
class ApiValueError(OpenApiException, ValueError):
def __init__(self, msg, path_to_item=None) -> None:
"""
Args:
msg (str): the exception message
Keyword Args:
path_to_item (list) the path to the exception in the
received_data dict. None if unset
"""
self.path_to_item = path_to_item
full_msg = msg
if path_to_item:
full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
super(ApiValueError, self).__init__(full_msg)
class ApiAttributeError(OpenApiException, AttributeError):
def __init__(self, msg, path_to_item=None) -> None:
"""
Raised when an attribute reference or assignment fails.
Args:
msg (str): the exception message
Keyword Args:
path_to_item (None/list) the path to the exception in the
received_data dict
"""
self.path_to_item = path_to_item
full_msg = msg
if path_to_item:
full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
super(ApiAttributeError, self).__init__(full_msg)
class ApiKeyError(OpenApiException, KeyError):
def __init__(self, msg, path_to_item=None) -> None:
"""
Args:
msg (str): the exception message
Keyword Args:
path_to_item (None/list) the path to the exception in the
received_data dict
"""
self.path_to_item = path_to_item
full_msg = msg
if path_to_item:
full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
super(ApiKeyError, self).__init__(full_msg)
class ApiException(OpenApiException):
def __init__(
self,
status=None,
reason=None,
http_resp=None,
*,
body: Optional[str] = None,
data: Optional[Any] = None,
) -> None:
self.status = status
self.reason = reason
self.body = body
self.data = data
self.headers = None
if http_resp:
if self.status is None:
self.status = http_resp.status
if self.reason is None:
self.reason = http_resp.reason
if self.body is None:
try:
self.body = http_resp.data.decode('utf-8')
except Exception:
pass
self.headers = http_resp.getheaders()
@classmethod
def from_response(
cls,
*,
http_resp,
body: Optional[str],
data: Optional[Any],
) -> Self:
if http_resp.status == 400:
raise BadRequestException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 401:
raise UnauthorizedException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 403:
raise ForbiddenException(http_resp=http_resp, body=body, data=data)
if http_resp.status == 404:
raise NotFoundException(http_resp=http_resp, body=body, data=data)
if 500 <= http_resp.status <= 599:
raise ServiceException(http_resp=http_resp, body=body, data=data)
raise ApiException(http_resp=http_resp, body=body, data=data)
def __str__(self):
"""Custom error messages for exception"""
error_message = "({0})\n"\
"Reason: {1}\n".format(self.status, self.reason)
if self.headers:
error_message += "HTTP response headers: {0}\n".format(
self.headers)
if self.data or self.body:
error_message += "HTTP response body: {0}\n".format(self.data or self.body)
return error_message
class BadRequestException(ApiException):
pass
class NotFoundException(ApiException):
pass
class UnauthorizedException(ApiException):
pass
class ForbiddenException(ApiException):
pass
class ServiceException(ApiException):
pass
def render_path(path_to_item):
"""Returns a string representation of a path"""
result = ""
for pth in path_to_item:
if isinstance(pth, int):
result += "[{0}]".format(pth)
else:
result += "['{0}']".format(pth)
return result

View File

@@ -0,0 +1,26 @@
# coding: utf-8
# flake8: noqa
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
# import models into model package
from openapi_client.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
from openapi_client.models.google_protobuf_any import GoogleProtobufAny
from openapi_client.models.ice_candidate import IceCandidate
from openapi_client.models.ice_session_description import IceSessionDescription
from openapi_client.models.knock import Knock
from openapi_client.models.list_knocks_response import ListKnocksResponse
from openapi_client.models.room import Room
from openapi_client.models.server import Server
from openapi_client.models.service import Service
from openapi_client.models.status import Status

View File

@@ -0,0 +1,95 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.ice_candidate import IceCandidate
from typing import Optional, Set
from typing_extensions import Self
class ClaimIceCandidatesResponse(BaseModel):
"""
ClaimIceCandidatesResponse
""" # noqa: E501
ice_candidates: Optional[List[IceCandidate]] = Field(default=None, alias="iceCandidates")
__properties: ClassVar[List[str]] = ["iceCandidates"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of ClaimIceCandidatesResponse from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in ice_candidates (list)
_items = []
if self.ice_candidates:
for _item in self.ice_candidates:
if _item:
_items.append(_item.to_dict())
_dict['iceCandidates'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of ClaimIceCandidatesResponse from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"iceCandidates": [IceCandidate.from_dict(_item) for _item in obj["iceCandidates"]] if obj.get("iceCandidates") is not None else None
})
return _obj

View File

@@ -0,0 +1,100 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self
class GoogleProtobufAny(BaseModel):
"""
Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.
""" # noqa: E501
type: Optional[StrictStr] = Field(default=None, description="The type of the serialized message.", alias="@type")
additional_properties: Dict[str, Any] = {}
__properties: ClassVar[List[str]] = ["@type"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of GoogleProtobufAny from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
* Fields in `self.additional_properties` are added to the output dict.
"""
excluded_fields: Set[str] = set([
"additional_properties",
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# puts key-value pairs in additional_properties in the top level
if self.additional_properties is not None:
for _key, _value in self.additional_properties.items():
_dict[_key] = _value
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of GoogleProtobufAny from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"@type": obj.get("@type")
})
# store additional fields in additional_properties
for _key in obj.keys():
if _key not in cls.__properties:
_obj.additional_properties[_key] = obj.get(_key)
return _obj

View File

@@ -0,0 +1,95 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self
class IceCandidate(BaseModel):
"""
IceCandidate
""" # noqa: E501
name: Optional[StrictStr] = None
candidate: Optional[StrictStr] = None
sdp_mid: Optional[StrictStr] = Field(default=None, alias="sdpMid")
sdp_line_index: Optional[StrictInt] = Field(default=None, alias="sdpLineIndex")
username_fragment: Optional[StrictStr] = Field(default=None, alias="usernameFragment")
__properties: ClassVar[List[str]] = ["name", "candidate", "sdpMid", "sdpLineIndex", "usernameFragment"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of IceCandidate from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of IceCandidate from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"candidate": obj.get("candidate"),
"sdpMid": obj.get("sdpMid"),
"sdpLineIndex": obj.get("sdpLineIndex"),
"usernameFragment": obj.get("usernameFragment")
})
return _obj

View File

@@ -0,0 +1,91 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self
class IceSessionDescription(BaseModel):
"""
IceSessionDescription
""" # noqa: E501
name: Optional[StrictStr] = Field(default=None, description="A unique identifier which can be used to send ICE candidates Maps to the session name")
sdp_type: Optional[StrictStr] = Field(default=None, description="Used to construct the remote description in WebRTC", alias="sdpType")
sdp: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["name", "sdpType", "sdp"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of IceSessionDescription from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of IceSessionDescription from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"sdpType": obj.get("sdpType"),
"sdp": obj.get("sdp")
})
return _obj

View File

@@ -0,0 +1,98 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.ice_session_description import IceSessionDescription
from typing import Optional, Set
from typing_extensions import Self
class Knock(BaseModel):
"""
Knock
""" # noqa: E501
name: Optional[StrictStr] = None
offer: Optional[IceSessionDescription] = Field(default=None, description="The service being connected too")
answer: Optional[IceSessionDescription] = None
__properties: ClassVar[List[str]] = ["name", "offer", "answer"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of Knock from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of offer
if self.offer:
_dict['offer'] = self.offer.to_dict()
# override the default output from pydantic by calling `to_dict()` of answer
if self.answer:
_dict['answer'] = self.answer.to_dict()
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of Knock from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"offer": IceSessionDescription.from_dict(obj["offer"]) if obj.get("offer") is not None else None,
"answer": IceSessionDescription.from_dict(obj["answer"]) if obj.get("answer") is not None else None
})
return _obj

View File

@@ -0,0 +1,95 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.knock import Knock
from typing import Optional, Set
from typing_extensions import Self
class ListKnocksResponse(BaseModel):
"""
ListKnocksResponse
""" # noqa: E501
knocks: Optional[List[Knock]] = None
__properties: ClassVar[List[str]] = ["knocks"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of ListKnocksResponse from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in knocks (list)
_items = []
if self.knocks:
for _item in self.knocks:
if _item:
_items.append(_item.to_dict())
_dict['knocks'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of ListKnocksResponse from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"knocks": [Knock.from_dict(_item) for _item in obj["knocks"]] if obj.get("knocks") is not None else None
})
return _obj

View File

@@ -0,0 +1,99 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.server import Server
from typing import Optional, Set
from typing_extensions import Self
class Room(BaseModel):
"""
Room
""" # noqa: E501
name: Optional[StrictStr] = None
display_name: Optional[StrictStr] = Field(default=None, alias="displayName")
servers: Optional[List[Server]] = None
__properties: ClassVar[List[str]] = ["name", "displayName", "servers"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of Room from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in servers (list)
_items = []
if self.servers:
for _item in self.servers:
if _item:
_items.append(_item.to_dict())
_dict['servers'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of Room from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"displayName": obj.get("displayName"),
"servers": [Server.from_dict(_item) for _item in obj["servers"]] if obj.get("servers") is not None else None
})
return _obj

View File

@@ -0,0 +1,103 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.service import Service
from typing import Optional, Set
from typing_extensions import Self
class Server(BaseModel):
"""
Server
""" # noqa: E501
name: Optional[StrictStr] = None
rooms: Optional[List[StrictStr]] = Field(default=None, description="Tracks which rooms the server should be listed in; this will not be set when a room is listed to preserve privacy of servers.")
auth_token: Optional[StrictStr] = Field(default=None, description="Used to authenticate requests which access knocks for this server or attempt to update, delete or create services. In future calls, add a header with the format: Authorization: Bearer <auth_token>", alias="authToken")
display_name: Optional[StrictStr] = Field(default=None, alias="displayName")
services: Optional[List[Service]] = None
__properties: ClassVar[List[str]] = ["name", "rooms", "authToken", "displayName", "services"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of Server from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in services (list)
_items = []
if self.services:
for _item in self.services:
if _item:
_items.append(_item.to_dict())
_dict['services'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of Server from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"rooms": obj.get("rooms"),
"authToken": obj.get("authToken"),
"displayName": obj.get("displayName"),
"services": [Service.from_dict(_item) for _item in obj["services"]] if obj.get("services") is not None else None
})
return _obj

View File

@@ -0,0 +1,91 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self
class Service(BaseModel):
"""
Service
""" # noqa: E501
name: Optional[StrictStr] = None
protocol: Optional[StrictStr] = None
version: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["name", "protocol", "version"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of Service from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of Service from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"name": obj.get("name"),
"protocol": obj.get("protocol"),
"version": obj.get("version")
})
return _obj

View File

@@ -0,0 +1,99 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.google_protobuf_any import GoogleProtobufAny
from typing import Optional, Set
from typing_extensions import Self
class Status(BaseModel):
"""
The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).
""" # noqa: E501
code: Optional[StrictInt] = Field(default=None, description="The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].")
message: Optional[StrictStr] = Field(default=None, description="A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.")
details: Optional[List[GoogleProtobufAny]] = Field(default=None, description="A list of messages that carry the error details. There is a common set of message types for APIs to use.")
__properties: ClassVar[List[str]] = ["code", "message", "details"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of Status from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in details (list)
_items = []
if self.details:
for _item in self.details:
if _item:
_items.append(_item.to_dict())
_dict['details'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of Status from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"code": obj.get("code"),
"message": obj.get("message"),
"details": [GoogleProtobufAny.from_dict(_item) for _item in obj["details"]] if obj.get("details") is not None else None
})
return _obj

View File

@@ -0,0 +1,255 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import io
import json
import re
import ssl
import urllib3
from openapi_client.exceptions import ApiException, ApiValueError
SUPPORTED_SOCKS_PROXIES = {"socks5", "socks5h", "socks4", "socks4a"}
RESTResponseType = urllib3.HTTPResponse
def is_socks_proxy_url(url):
if url is None:
return False
split_section = url.split("://")
if len(split_section) < 2:
return False
else:
return split_section[0].lower() in SUPPORTED_SOCKS_PROXIES
class RESTResponse(io.IOBase):
def __init__(self, resp) -> None:
self.response = resp
self.status = resp.status
self.reason = resp.reason
self.data = None
def read(self):
if self.data is None:
self.data = self.response.data
return self.data
def getheaders(self):
"""Returns a dictionary of the response headers."""
return self.response.headers
def getheader(self, name, default=None):
"""Returns a given response header."""
return self.response.headers.get(name, default)
class RESTClientObject:
def __init__(self, configuration) -> None:
# urllib3.PoolManager will pass all kw parameters to connectionpool
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501
# Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501
# cert_reqs
if configuration.verify_ssl:
cert_reqs = ssl.CERT_REQUIRED
else:
cert_reqs = ssl.CERT_NONE
pool_args = {
"cert_reqs": cert_reqs,
"ca_certs": configuration.ssl_ca_cert,
"cert_file": configuration.cert_file,
"key_file": configuration.key_file,
}
if configuration.assert_hostname is not None:
pool_args['assert_hostname'] = (
configuration.assert_hostname
)
if configuration.retries is not None:
pool_args['retries'] = configuration.retries
if configuration.tls_server_name:
pool_args['server_hostname'] = configuration.tls_server_name
if configuration.socket_options is not None:
pool_args['socket_options'] = configuration.socket_options
if configuration.connection_pool_maxsize is not None:
pool_args['maxsize'] = configuration.connection_pool_maxsize
# https pool manager
self.pool_manager: urllib3.PoolManager
if configuration.proxy:
if is_socks_proxy_url(configuration.proxy):
from urllib3.contrib.socks import SOCKSProxyManager
pool_args["proxy_url"] = configuration.proxy
pool_args["headers"] = configuration.proxy_headers
self.pool_manager = SOCKSProxyManager(**pool_args)
else:
pool_args["proxy_url"] = configuration.proxy
pool_args["proxy_headers"] = configuration.proxy_headers
self.pool_manager = urllib3.ProxyManager(**pool_args)
else:
self.pool_manager = urllib3.PoolManager(**pool_args)
def request(
self,
method,
url,
headers=None,
body=None,
post_params=None,
_request_timeout=None
):
"""Perform requests.
:param method: http request method
:param url: http request url
:param headers: http request headers
:param body: request json body, for `application/json`
:param post_params: request post parameters,
`application/x-www-form-urlencoded`
and `multipart/form-data`
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
"""
method = method.upper()
assert method in [
'GET',
'HEAD',
'DELETE',
'POST',
'PUT',
'PATCH',
'OPTIONS'
]
if post_params and body:
raise ApiValueError(
"body parameter cannot be used with post_params parameter."
)
post_params = post_params or {}
headers = headers or {}
timeout = None
if _request_timeout:
if isinstance(_request_timeout, (int, float)):
timeout = urllib3.Timeout(total=_request_timeout)
elif (
isinstance(_request_timeout, tuple)
and len(_request_timeout) == 2
):
timeout = urllib3.Timeout(
connect=_request_timeout[0],
read=_request_timeout[1]
)
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# no content type provided or payload is json
content_type = headers.get('Content-Type')
if (
not content_type
or re.search('json', content_type, re.IGNORECASE)
):
request_body = None
if body is not None:
request_body = json.dumps(body)
r = self.pool_manager.request(
method,
url,
body=request_body,
timeout=timeout,
headers=headers,
preload_content=False
)
elif content_type == 'application/x-www-form-urlencoded':
r = self.pool_manager.request(
method,
url,
fields=post_params,
encode_multipart=False,
timeout=timeout,
headers=headers,
preload_content=False
)
elif content_type == 'multipart/form-data':
# must del headers['Content-Type'], or the correct
# Content-Type which generated by urllib3 will be
# overwritten.
del headers['Content-Type']
r = self.pool_manager.request(
method,
url,
fields=post_params,
encode_multipart=True,
timeout=timeout,
headers=headers,
preload_content=False
)
# Pass a `string` parameter directly in the body to support
# other content types than JSON when `body` argument is
# provided in serialized form.
elif isinstance(body, str) or isinstance(body, bytes):
r = self.pool_manager.request(
method,
url,
body=body,
timeout=timeout,
headers=headers,
preload_content=False
)
elif headers['Content-Type'] == 'text/plain' and isinstance(body, bool):
request_body = "true" if body else "false"
r = self.pool_manager.request(
method,
url,
body=request_body,
preload_content=False,
timeout=timeout,
headers=headers)
else:
# Cannot generate the request from given parameters
msg = """Cannot prepare a request message for provided
arguments. Please check that your arguments match
declared content type."""
raise ApiException(status=0, reason=msg)
# For `GET`, `HEAD`
else:
r = self.pool_manager.request(
method,
url,
fields={},
timeout=timeout,
headers=headers,
preload_content=False
)
except urllib3.exceptions.SSLError as e:
msg = "\n".join([type(e).__name__, str(e)])
raise ApiException(status=0, reason=msg)
return RESTResponse(r)

View File

@@ -0,0 +1,71 @@
[tool.poetry]
name = "openapi_client"
version = "1.0.0"
description = "PeerNetService API"
authors = ["OpenAPI Generator Community <team@openapitools.org>"]
license = "NoLicense"
readme = "README.md"
repository = "https://github.com/GIT_USER_ID/GIT_REPO_ID"
keywords = ["OpenAPI", "OpenAPI-Generator", "PeerNetService API"]
include = ["openapi_client/py.typed"]
[tool.poetry.dependencies]
python = "^3.7"
urllib3 = ">= 1.25.3"
python-dateutil = ">=2.8.2"
pydantic = ">=2"
typing-extensions = ">=4.7.1"
[tool.poetry.dev-dependencies]
pytest = ">=7.2.1"
tox = ">=3.9.0"
flake8 = ">=4.0.0"
types-python-dateutil = ">=2.8.19.14"
mypy = "1.4.1"
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[tool.pylint.'MESSAGES CONTROL']
extension-pkg-whitelist = "pydantic"
[tool.mypy]
files = [
"openapi_client",
#"test", # auto-generated tests
"tests", # hand-written tests
]
# TODO: enable "strict" once all these individual checks are passing
# strict = true
# List from: https://mypy.readthedocs.io/en/stable/existing_code.html#introduce-stricter-options
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true
## Getting these passing should be easy
strict_equality = true
strict_concatenate = true
## Strongly recommend enabling this one as soon as you can
check_untyped_defs = true
## These shouldn't be too much additional work, but may be tricky to
## get passing if you use a lot of untyped libraries
disallow_subclassing_any = true
disallow_untyped_decorators = true
disallow_any_generics = true
### These next few are various gradations of forcing use of type annotations
#disallow_untyped_calls = true
#disallow_incomplete_defs = true
#disallow_untyped_defs = true
#
### This one isn't too hard to get passing, but return on investment is lower
#no_implicit_reexport = true
#
### This one can be tricky to get passing if you use a lot of untyped libraries
#warn_return_any = true

View File

@@ -0,0 +1,5 @@
python_dateutil >= 2.5.3
setuptools >= 21.0.0
urllib3 >= 1.25.3, < 2.1.0
pydantic >= 2
typing-extensions >= 4.7.1

View File

@@ -0,0 +1,2 @@
[flake8]
max-line-length=99

View File

@@ -0,0 +1,49 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from setuptools import setup, find_packages # noqa: H301
# To install the library, run the following
#
# python setup.py install
#
# prerequisite: setuptools
# http://pypi.python.org/pypi/setuptools
NAME = "openapi-client"
VERSION = "1.0.0"
PYTHON_REQUIRES = ">=3.7"
REQUIRES = [
"urllib3 >= 1.25.3, < 2.1.0",
"python-dateutil",
"pydantic >= 2",
"typing-extensions >= 4.7.1",
]
setup(
name=NAME,
version=VERSION,
description="PeerNetService API",
author="OpenAPI Generator community",
author_email="team@openapitools.org",
url="",
keywords=["OpenAPI", "OpenAPI-Generator", "PeerNetService API"],
install_requires=REQUIRES,
packages=find_packages(exclude=["test", "tests"]),
include_package_data=True,
long_description_content_type='text/markdown',
long_description="""\
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
""", # noqa: E501
package_data={"openapi_client": ["py.typed"]},
)

View File

@@ -0,0 +1,5 @@
pytest~=7.1.3
pytest-cov>=2.8.1
pytest-randomly>=3.12.0
mypy>=1.4.1
types-python-dateutil>=2.8.19

View File

View File

@@ -0,0 +1,58 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
class TestClaimIceCandidatesResponse(unittest.TestCase):
"""ClaimIceCandidatesResponse unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> ClaimIceCandidatesResponse:
"""Test ClaimIceCandidatesResponse
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `ClaimIceCandidatesResponse`
"""
model = ClaimIceCandidatesResponse()
if include_optional:
return ClaimIceCandidatesResponse(
ice_candidates = [
openapi_client.models.ice_candidate.IceCandidate(
name = '',
candidate = '',
sdp_mid = '',
sdp_line_index = 56,
username_fragment = '', )
]
)
else:
return ClaimIceCandidatesResponse(
)
"""
def testClaimIceCandidatesResponse(self):
"""Test ClaimIceCandidatesResponse"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,51 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.google_protobuf_any import GoogleProtobufAny
class TestGoogleProtobufAny(unittest.TestCase):
"""GoogleProtobufAny unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> GoogleProtobufAny:
"""Test GoogleProtobufAny
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `GoogleProtobufAny`
"""
model = GoogleProtobufAny()
if include_optional:
return GoogleProtobufAny(
type = ''
)
else:
return GoogleProtobufAny(
)
"""
def testGoogleProtobufAny(self):
"""Test GoogleProtobufAny"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,55 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.ice_candidate import IceCandidate
class TestIceCandidate(unittest.TestCase):
"""IceCandidate unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> IceCandidate:
"""Test IceCandidate
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `IceCandidate`
"""
model = IceCandidate()
if include_optional:
return IceCandidate(
name = '',
candidate = '',
sdp_mid = '',
sdp_line_index = 56,
username_fragment = ''
)
else:
return IceCandidate(
)
"""
def testIceCandidate(self):
"""Test IceCandidate"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,53 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.ice_session_description import IceSessionDescription
class TestIceSessionDescription(unittest.TestCase):
"""IceSessionDescription unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> IceSessionDescription:
"""Test IceSessionDescription
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `IceSessionDescription`
"""
model = IceSessionDescription()
if include_optional:
return IceSessionDescription(
name = '',
sdp_type = '',
sdp = ''
)
else:
return IceSessionDescription(
)
"""
def testIceSessionDescription(self):
"""Test IceSessionDescription"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,63 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.knock import Knock
class TestKnock(unittest.TestCase):
"""Knock unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> Knock:
"""Test Knock
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `Knock`
"""
model = Knock()
if include_optional:
return Knock(
name = '',
service = openapi_client.models.service.Service(
name = '',
protocol = '',
version = '', ),
offer = openapi_client.models.ice_session_description.IceSessionDescription(
name = '',
sdp_type = '',
sdp = '', ),
answer = openapi_client.models.ice_session_description.IceSessionDescription(
name = '',
sdp_type = '',
sdp = '', )
)
else:
return Knock(
)
"""
def testKnock(self):
"""Test Knock"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,63 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.list_knocks_response import ListKnocksResponse
class TestListKnocksResponse(unittest.TestCase):
"""ListKnocksResponse unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> ListKnocksResponse:
"""Test ListKnocksResponse
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `ListKnocksResponse`
"""
model = ListKnocksResponse()
if include_optional:
return ListKnocksResponse(
knocks = [
openapi_client.models.knock.Knock(
name = '',
service = null,
offer = openapi_client.models.ice_session_description.IceSessionDescription(
name = '',
sdp_type = '',
sdp = '', ),
answer = openapi_client.models.ice_session_description.IceSessionDescription(
name = '',
sdp_type = '',
sdp = '', ), )
]
)
else:
return ListKnocksResponse(
)
"""
def testListKnocksResponse(self):
"""Test ListKnocksResponse"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,91 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.api.peer_net_service_api import PeerNetServiceApi
class TestPeerNetServiceApi(unittest.TestCase):
"""PeerNetServiceApi unit test stubs"""
def setUp(self) -> None:
self.api = PeerNetServiceApi()
def tearDown(self) -> None:
pass
def test_peer_net_service_claim_ice_candidates(self) -> None:
"""Test case for peer_net_service_claim_ice_candidates
"""
pass
def test_peer_net_service_create_ice_candidate(self) -> None:
"""Test case for peer_net_service_create_ice_candidate
"""
pass
def test_peer_net_service_create_knock(self) -> None:
"""Test case for peer_net_service_create_knock
"""
pass
def test_peer_net_service_create_server(self) -> None:
"""Test case for peer_net_service_create_server
"""
pass
def test_peer_net_service_create_service(self) -> None:
"""Test case for peer_net_service_create_service
"""
pass
def test_peer_net_service_delete_server(self) -> None:
"""Test case for peer_net_service_delete_server
"""
pass
def test_peer_net_service_delete_service(self) -> None:
"""Test case for peer_net_service_delete_service
"""
pass
def test_peer_net_service_get_room(self) -> None:
"""Test case for peer_net_service_get_room
"""
pass
def test_peer_net_service_list_knocks(self) -> None:
"""Test case for peer_net_service_list_knocks
"""
pass
def test_peer_net_service_update_knock(self) -> None:
"""Test case for peer_net_service_update_knock
"""
pass
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,67 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.room import Room
class TestRoom(unittest.TestCase):
"""Room unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> Room:
"""Test Room
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `Room`
"""
model = Room()
if include_optional:
return Room(
name = '',
display_name = '',
servers = [
openapi_client.models.server.Server(
name = '',
rooms = [
''
],
auth_token = '',
display_name = '',
services = [
openapi_client.models.service.Service(
name = '',
protocol = '',
version = '', )
], )
]
)
else:
return Room(
)
"""
def testRoom(self):
"""Test Room"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,62 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.server import Server
class TestServer(unittest.TestCase):
"""Server unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> Server:
"""Test Server
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `Server`
"""
model = Server()
if include_optional:
return Server(
name = '',
rooms = [
''
],
auth_token = '',
display_name = '',
services = [
openapi_client.models.service.Service(
name = '',
protocol = '',
version = '', )
]
)
else:
return Server(
)
"""
def testServer(self):
"""Test Server"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,53 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.service import Service
class TestService(unittest.TestCase):
"""Service unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> Service:
"""Test Service
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `Service`
"""
model = Service()
if include_optional:
return Service(
name = '',
protocol = '',
version = ''
)
else:
return Service(
)
"""
def testService(self):
"""Test Service"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,55 @@
# coding: utf-8
"""
PeerNetService API
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.0.1
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.status import Status
class TestStatus(unittest.TestCase):
"""Status unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> Status:
"""Test Status
include_option is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `Status`
"""
model = Status()
if include_optional:
return Status(
code = 56,
message = '',
details = [
{ }
]
)
else:
return Status(
)
"""
def testStatus(self):
"""Test Status"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,9 @@
[tox]
envlist = py3
[testenv]
deps=-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands=
pytest --cov=openapi_client

57
demo_server/git_push.sh Normal file
View File

@@ -0,0 +1,57 @@
#!/bin/sh
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
#
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
git_user_id=$1
git_repo_id=$2
release_note=$3
git_host=$4
if [ "$git_host" = "" ]; then
git_host="github.com"
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
fi
if [ "$git_user_id" = "" ]; then
git_user_id="GIT_USER_ID"
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
fi
if [ "$git_repo_id" = "" ]; then
git_repo_id="GIT_REPO_ID"
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
fi
if [ "$release_note" = "" ]; then
release_note="Minor update"
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
fi
# Initialize the local directory as a Git repository
git init
# Adds the files in the local repository and stages them for commit.
git add .
# Commits the tracked changes and prepares them to be pushed to a remote repository.
git commit -m "$release_note"
# Sets the new remote
git_remote=$(git remote)
if [ "$git_remote" = "" ]; then # git remote not defined
if [ "$GIT_TOKEN" = "" ]; then
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
else
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
fi
fi
git pull origin master
# Pushes (Forces) the changes in the local repository up to the remote repository
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
git push origin master 2>&1 | grep -v 'To https'

View File

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python3
import connexion
from openapi_server import encoder
def main():
app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml',
arguments={'title': 'PeerNetService API'},
pythonic_params=True)
app.run(port=8080)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,227 @@
import connexion
from typing import Dict
from typing import Tuple
from typing import Union
from openapi_server.models.claim_ice_candidates_response import ClaimIceCandidatesResponse # noqa: E501
from openapi_server.models.ice_candidate import IceCandidate # noqa: E501
from openapi_server.models.knock import Knock # noqa: E501
from openapi_server.models.list_knocks_response import ListKnocksResponse # noqa: E501
from openapi_server.models.room import Room # noqa: E501
from openapi_server.models.server import Server # noqa: E501
from openapi_server.models.service import Service # noqa: E501
from openapi_server.models.status import Status # noqa: E501
from openapi_server import util
servers = {}
rooms = {}
knocks = {}
sessions = {}
def peer_net_service_claim_ice_candidates(session): # noqa: E501
"""peer_net_service_claim_ice_candidates
Acts as both List and Delete atomically. # noqa: E501
:param session: The session id.
:type session: str
:param name:
:type name: str
:rtype: Union[ClaimIceCandidatesResponse, Tuple[ClaimIceCandidatesResponse, int], Tuple[ClaimIceCandidatesResponse, int, Dict[str, str]]
"""
if session not in sessions:
return 'not found', 404
candidates = [sessions[session][k] for k in sessions[session]]
sessions[session] = {}
return ClaimIceCandidatesResponse(ice_candidates=candidates)
def peer_net_service_create_ice_candidate(session, ice_candidate=None, target_session=None): # noqa: E501
"""peer_net_service_create_ice_candidate
# noqa: E501
:param session: The session id.
:type session: str
:param ice_candidate:
:type ice_candidate: dict | bytes
:param target_session:
:type target_session: str
:rtype: Union[IceCandidate, Tuple[IceCandidate, int], Tuple[IceCandidate, int, Dict[str, str]]
"""
if connexion.request.is_json:
ice_candidate = IceCandidate.from_dict(connexion.request.get_json()) # noqa: E501
sessions[session][ice_candidate.name] = ice_candidate
return ice_candidate
def peer_net_service_create_knock(server, service, knock=None): # noqa: E501
"""peer_net_service_create_knock
Creates a knock that will be answered by the peer; the signaler may delete the knock, regardless of the state, when it ages. # noqa: E501
:param server: The server id.
:type server: str
:param service: The service id.
:type service: str
:param knock:
:type knock: dict | bytes
:rtype: Union[Knock, Tuple[Knock, int], Tuple[Knock, int, Dict[str, str]]
"""
if connexion.request.is_json:
knock = Knock.from_dict(connexion.request.get_json()) # noqa: E501
print(knock)
if server not in servers or service not in [s.name for s in servers[server].services]:
return 'not found', 404
knocks[server][service][knock.name] = knock
sessions[knock.offer.name] = {}
return knock
def peer_net_service_create_server(server=None): # noqa: E501
"""peer_net_service_create_server
# noqa: E501
:param server:
:type server: dict | bytes
:rtype: Union[Server, Tuple[Server, int], Tuple[Server, int, Dict[str, str]]
"""
if connexion.request.is_json:
server = Server.from_dict(connexion.request.get_json()) # noqa: E501
servers[server.name] = server
for room in server.rooms:
if room not in rooms:
rooms[room] = {}
rooms[room][server.name] = server
knocks[server.name] = {}
for service in server.services:
knocks[server.name][service.name] = {}
return server
def peer_net_service_create_service(server, service): # noqa: E501
"""peer_net_service_create_service
# noqa: E501
:param server: The server id.
:type server: str
:param service:
:type service: dict | bytes
:rtype: Union[Service, Tuple[Service, int], Tuple[Service, int, Dict[str, str]]
"""
if connexion.request.is_json:
service = Service.from_dict(connexion.request.get_json()) # noqa: E501
return 'do some magic!'
def peer_net_service_delete_server(name=None): # noqa: E501
"""peer_net_service_delete_server
# noqa: E501
:param name:
:type name: str
:rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]]
"""
return 'do some magic!'
def peer_net_service_delete_service(server, service): # noqa: E501
"""peer_net_service_delete_service
# noqa: E501
:param server: The server id.
:type server: str
:param service: The service id.
:type service: str
:rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]]
"""
return 'do some magic!'
def peer_net_service_get_knock(server, service, knock): # noqa: E501
"""peer_net_service_get_knock
# noqa: E501
:param server: The server id.
:type server: str
:param service: The service id.
:type service: str
:param knock: The knock id.
:type knock: str
:rtype: Union[Knock, Tuple[Knock, int], Tuple[Knock, int, Dict[str, str]]
"""
if server not in knocks or service not in knocks[server] or knock not in knocks[server][service]:
return 'not found', 404
return knocks[server][service][knock]
def peer_net_service_get_room(room): # noqa: E501
"""peer_net_service_get_room
# noqa: E501
:param room: The room id.
:type room: str
:rtype: Union[Room, Tuple[Room, int], Tuple[Room, int, Dict[str, str]]
"""
if room not in rooms:
return 'not found', 404
s = []
for server in rooms[room]:
s.append(servers[server])
return Room(name=room, servers=s)
def peer_net_service_list_knocks(server, service): # noqa: E501
"""peer_net_service_list_knocks
# noqa: E501
:param server: The server id.
:type server: str
:param service: The service id.
:type service: str
:rtype: Union[ListKnocksResponse, Tuple[ListKnocksResponse, int], Tuple[ListKnocksResponse, int, Dict[str, str]]
"""
if server not in knocks or service not in knocks[server]:
return 'not found', 404
return ListKnocksResponse(knocks=[knocks[server][service][k] for k in knocks[server][service]])
def peer_net_service_update_knock(server, service, knock, knock2=None): # noqa: E501
"""peer_net_service_update_knock
# noqa: E501
:param server: The server id.
:type server: str
:param service: The service id.
:type service: str
:param knock: The knock id.
:type knock: str
:param knock2:
:type knock2: dict | bytes
:rtype: Union[Knock, Tuple[Knock, int], Tuple[Knock, int, Dict[str, str]]
"""
if connexion.request.is_json:
knock2 = Knock.from_dict(connexion.request.get_json()) # noqa: E501
if server not in servers or service not in [s.name for s in servers[server].services]:
return 'not found', 404
knocks[server][service][knock] = knock2
sessions[knock2.answer.name] = {}
return knock2

View File

@@ -0,0 +1,2 @@
from typing import List

View File

@@ -0,0 +1,19 @@
from connexion.apps.flask_app import FlaskJSONEncoder
from openapi_server.models.base_model import Model
class JSONEncoder(FlaskJSONEncoder):
include_nulls = False
def default(self, o):
if isinstance(o, Model):
dikt = {}
for attr in o.openapi_types:
value = getattr(o, attr)
if value is None and not self.include_nulls:
continue
attr = o.attribute_map[attr]
dikt[attr] = value
return dikt
return FlaskJSONEncoder.default(self, o)

View File

@@ -0,0 +1,12 @@
# flake8: noqa
# import models into model package
from openapi_server.models.claim_ice_candidates_response import ClaimIceCandidatesResponse
from openapi_server.models.google_protobuf_any import GoogleProtobufAny
from openapi_server.models.ice_candidate import IceCandidate
from openapi_server.models.ice_session_description import IceSessionDescription
from openapi_server.models.knock import Knock
from openapi_server.models.list_knocks_response import ListKnocksResponse
from openapi_server.models.room import Room
from openapi_server.models.server import Server
from openapi_server.models.service import Service
from openapi_server.models.status import Status

View File

@@ -0,0 +1,68 @@
import pprint
import typing
from openapi_server import util
T = typing.TypeVar('T')
class Model:
# openapiTypes: The key is attribute name and the
# value is attribute type.
openapi_types: typing.Dict[str, type] = {}
# attributeMap: The key is attribute name and the
# value is json key in definition.
attribute_map: typing.Dict[str, str] = {}
@classmethod
def from_dict(cls: typing.Type[T], dikt) -> T:
"""Returns the dict as a model"""
return util.deserialize_model(dikt, cls)
def to_dict(self):
"""Returns the model properties as a dict
:rtype: dict
"""
result = {}
for attr in self.openapi_types:
value = getattr(self, attr)
if isinstance(value, list):
result[attr] = list(map(
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
value
))
elif hasattr(value, "to_dict"):
result[attr] = value.to_dict()
elif isinstance(value, dict):
result[attr] = dict(map(
lambda item: (item[0], item[1].to_dict())
if hasattr(item[1], "to_dict") else item,
value.items()
))
else:
result[attr] = value
return result
def to_str(self):
"""Returns the string representation of the model
:rtype: str
"""
return pprint.pformat(self.to_dict())
def __repr__(self):
"""For `print` and `pprint`"""
return self.to_str()
def __eq__(self, other):
"""Returns true if both objects are equal"""
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Returns true if both objects are not equal"""
return not self == other

View File

@@ -0,0 +1,63 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.ice_candidate import IceCandidate
from openapi_server import util
from openapi_server.models.ice_candidate import IceCandidate # noqa: E501
class ClaimIceCandidatesResponse(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, ice_candidates=None): # noqa: E501
"""ClaimIceCandidatesResponse - a model defined in OpenAPI
:param ice_candidates: The ice_candidates of this ClaimIceCandidatesResponse. # noqa: E501
:type ice_candidates: List[IceCandidate]
"""
self.openapi_types = {
'ice_candidates': List[IceCandidate]
}
self.attribute_map = {
'ice_candidates': 'iceCandidates'
}
self._ice_candidates = ice_candidates
@classmethod
def from_dict(cls, dikt) -> 'ClaimIceCandidatesResponse':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The ClaimIceCandidatesResponse of this ClaimIceCandidatesResponse. # noqa: E501
:rtype: ClaimIceCandidatesResponse
"""
return util.deserialize_model(dikt, cls)
@property
def ice_candidates(self) -> List[IceCandidate]:
"""Gets the ice_candidates of this ClaimIceCandidatesResponse.
:return: The ice_candidates of this ClaimIceCandidatesResponse.
:rtype: List[IceCandidate]
"""
return self._ice_candidates
@ice_candidates.setter
def ice_candidates(self, ice_candidates: List[IceCandidate]):
"""Sets the ice_candidates of this ClaimIceCandidatesResponse.
:param ice_candidates: The ice_candidates of this ClaimIceCandidatesResponse.
:type ice_candidates: List[IceCandidate]
"""
self._ice_candidates = ice_candidates

View File

@@ -0,0 +1,63 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server import util
class GoogleProtobufAny(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, type=None): # noqa: E501
"""GoogleProtobufAny - a model defined in OpenAPI
:param type: The type of this GoogleProtobufAny. # noqa: E501
:type type: str
"""
self.openapi_types = {
'type': str
}
self.attribute_map = {
'type': '@type'
}
self._type = type
@classmethod
def from_dict(cls, dikt) -> 'GoogleProtobufAny':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The GoogleProtobufAny of this GoogleProtobufAny. # noqa: E501
:rtype: GoogleProtobufAny
"""
return util.deserialize_model(dikt, cls)
@property
def type(self) -> str:
"""Gets the type of this GoogleProtobufAny.
The type of the serialized message. # noqa: E501
:return: The type of this GoogleProtobufAny.
:rtype: str
"""
return self._type
@type.setter
def type(self, type: str):
"""Sets the type of this GoogleProtobufAny.
The type of the serialized message. # noqa: E501
:param type: The type of this GoogleProtobufAny.
:type type: str
"""
self._type = type

View File

@@ -0,0 +1,165 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server import util
class IceCandidate(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, candidate=None, sdp_mid=None, sdp_line_index=None, username_fragment=None): # noqa: E501
"""IceCandidate - a model defined in OpenAPI
:param name: The name of this IceCandidate. # noqa: E501
:type name: str
:param candidate: The candidate of this IceCandidate. # noqa: E501
:type candidate: str
:param sdp_mid: The sdp_mid of this IceCandidate. # noqa: E501
:type sdp_mid: str
:param sdp_line_index: The sdp_line_index of this IceCandidate. # noqa: E501
:type sdp_line_index: int
:param username_fragment: The username_fragment of this IceCandidate. # noqa: E501
:type username_fragment: str
"""
self.openapi_types = {
'name': str,
'candidate': str,
'sdp_mid': str,
'sdp_line_index': int,
'username_fragment': str
}
self.attribute_map = {
'name': 'name',
'candidate': 'candidate',
'sdp_mid': 'sdpMid',
'sdp_line_index': 'sdpLineIndex',
'username_fragment': 'usernameFragment'
}
self._name = name
self._candidate = candidate
self._sdp_mid = sdp_mid
self._sdp_line_index = sdp_line_index
self._username_fragment = username_fragment
@classmethod
def from_dict(cls, dikt) -> 'IceCandidate':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The IceCandidate of this IceCandidate. # noqa: E501
:rtype: IceCandidate
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this IceCandidate.
:return: The name of this IceCandidate.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this IceCandidate.
:param name: The name of this IceCandidate.
:type name: str
"""
self._name = name
@property
def candidate(self) -> str:
"""Gets the candidate of this IceCandidate.
:return: The candidate of this IceCandidate.
:rtype: str
"""
return self._candidate
@candidate.setter
def candidate(self, candidate: str):
"""Sets the candidate of this IceCandidate.
:param candidate: The candidate of this IceCandidate.
:type candidate: str
"""
self._candidate = candidate
@property
def sdp_mid(self) -> str:
"""Gets the sdp_mid of this IceCandidate.
:return: The sdp_mid of this IceCandidate.
:rtype: str
"""
return self._sdp_mid
@sdp_mid.setter
def sdp_mid(self, sdp_mid: str):
"""Sets the sdp_mid of this IceCandidate.
:param sdp_mid: The sdp_mid of this IceCandidate.
:type sdp_mid: str
"""
self._sdp_mid = sdp_mid
@property
def sdp_line_index(self) -> int:
"""Gets the sdp_line_index of this IceCandidate.
:return: The sdp_line_index of this IceCandidate.
:rtype: int
"""
return self._sdp_line_index
@sdp_line_index.setter
def sdp_line_index(self, sdp_line_index: int):
"""Sets the sdp_line_index of this IceCandidate.
:param sdp_line_index: The sdp_line_index of this IceCandidate.
:type sdp_line_index: int
"""
self._sdp_line_index = sdp_line_index
@property
def username_fragment(self) -> str:
"""Gets the username_fragment of this IceCandidate.
:return: The username_fragment of this IceCandidate.
:rtype: str
"""
return self._username_fragment
@username_fragment.setter
def username_fragment(self, username_fragment: str):
"""Sets the username_fragment of this IceCandidate.
:param username_fragment: The username_fragment of this IceCandidate.
:type username_fragment: str
"""
self._username_fragment = username_fragment

View File

@@ -0,0 +1,117 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server import util
class IceSessionDescription(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, sdp_type=None, sdp=None): # noqa: E501
"""IceSessionDescription - a model defined in OpenAPI
:param name: The name of this IceSessionDescription. # noqa: E501
:type name: str
:param sdp_type: The sdp_type of this IceSessionDescription. # noqa: E501
:type sdp_type: str
:param sdp: The sdp of this IceSessionDescription. # noqa: E501
:type sdp: str
"""
self.openapi_types = {
'name': str,
'sdp_type': str,
'sdp': str
}
self.attribute_map = {
'name': 'name',
'sdp_type': 'sdpType',
'sdp': 'sdp'
}
self._name = name
self._sdp_type = sdp_type
self._sdp = sdp
@classmethod
def from_dict(cls, dikt) -> 'IceSessionDescription':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The IceSessionDescription of this IceSessionDescription. # noqa: E501
:rtype: IceSessionDescription
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this IceSessionDescription.
A unique identifier which can be used to send ICE candidates Maps to the session name # noqa: E501
:return: The name of this IceSessionDescription.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this IceSessionDescription.
A unique identifier which can be used to send ICE candidates Maps to the session name # noqa: E501
:param name: The name of this IceSessionDescription.
:type name: str
"""
self._name = name
@property
def sdp_type(self) -> str:
"""Gets the sdp_type of this IceSessionDescription.
Used to construct the remote description in WebRTC # noqa: E501
:return: The sdp_type of this IceSessionDescription.
:rtype: str
"""
return self._sdp_type
@sdp_type.setter
def sdp_type(self, sdp_type: str):
"""Sets the sdp_type of this IceSessionDescription.
Used to construct the remote description in WebRTC # noqa: E501
:param sdp_type: The sdp_type of this IceSessionDescription.
:type sdp_type: str
"""
self._sdp_type = sdp_type
@property
def sdp(self) -> str:
"""Gets the sdp of this IceSessionDescription.
:return: The sdp of this IceSessionDescription.
:rtype: str
"""
return self._sdp
@sdp.setter
def sdp(self, sdp: str):
"""Sets the sdp of this IceSessionDescription.
:param sdp: The sdp of this IceSessionDescription.
:type sdp: str
"""
self._sdp = sdp

View File

@@ -0,0 +1,117 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.ice_session_description import IceSessionDescription
from openapi_server import util
from openapi_server.models.ice_session_description import IceSessionDescription # noqa: E501
class Knock(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, offer=None, answer=None): # noqa: E501
"""Knock - a model defined in OpenAPI
:param name: The name of this Knock. # noqa: E501
:type name: str
:param offer: The offer of this Knock. # noqa: E501
:type offer: IceSessionDescription
:param answer: The answer of this Knock. # noqa: E501
:type answer: IceSessionDescription
"""
self.openapi_types = {
'name': str,
'offer': IceSessionDescription,
'answer': IceSessionDescription
}
self.attribute_map = {
'name': 'name',
'offer': 'offer',
'answer': 'answer'
}
self._name = name
self._offer = offer
self._answer = answer
@classmethod
def from_dict(cls, dikt) -> 'Knock':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The Knock of this Knock. # noqa: E501
:rtype: Knock
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this Knock.
:return: The name of this Knock.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this Knock.
:param name: The name of this Knock.
:type name: str
"""
self._name = name
@property
def offer(self) -> IceSessionDescription:
"""Gets the offer of this Knock.
The service being connected too # noqa: E501
:return: The offer of this Knock.
:rtype: IceSessionDescription
"""
return self._offer
@offer.setter
def offer(self, offer: IceSessionDescription):
"""Sets the offer of this Knock.
The service being connected too # noqa: E501
:param offer: The offer of this Knock.
:type offer: IceSessionDescription
"""
self._offer = offer
@property
def answer(self) -> IceSessionDescription:
"""Gets the answer of this Knock.
:return: The answer of this Knock.
:rtype: IceSessionDescription
"""
return self._answer
@answer.setter
def answer(self, answer: IceSessionDescription):
"""Sets the answer of this Knock.
:param answer: The answer of this Knock.
:type answer: IceSessionDescription
"""
self._answer = answer

View File

@@ -0,0 +1,63 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.knock import Knock
from openapi_server import util
from openapi_server.models.knock import Knock # noqa: E501
class ListKnocksResponse(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, knocks=None): # noqa: E501
"""ListKnocksResponse - a model defined in OpenAPI
:param knocks: The knocks of this ListKnocksResponse. # noqa: E501
:type knocks: List[Knock]
"""
self.openapi_types = {
'knocks': List[Knock]
}
self.attribute_map = {
'knocks': 'knocks'
}
self._knocks = knocks
@classmethod
def from_dict(cls, dikt) -> 'ListKnocksResponse':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The ListKnocksResponse of this ListKnocksResponse. # noqa: E501
:rtype: ListKnocksResponse
"""
return util.deserialize_model(dikt, cls)
@property
def knocks(self) -> List[Knock]:
"""Gets the knocks of this ListKnocksResponse.
:return: The knocks of this ListKnocksResponse.
:rtype: List[Knock]
"""
return self._knocks
@knocks.setter
def knocks(self, knocks: List[Knock]):
"""Sets the knocks of this ListKnocksResponse.
:param knocks: The knocks of this ListKnocksResponse.
:type knocks: List[Knock]
"""
self._knocks = knocks

View File

@@ -0,0 +1,115 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.server import Server
from openapi_server import util
from openapi_server.models.server import Server # noqa: E501
class Room(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, display_name=None, servers=None): # noqa: E501
"""Room - a model defined in OpenAPI
:param name: The name of this Room. # noqa: E501
:type name: str
:param display_name: The display_name of this Room. # noqa: E501
:type display_name: str
:param servers: The servers of this Room. # noqa: E501
:type servers: List[Server]
"""
self.openapi_types = {
'name': str,
'display_name': str,
'servers': List[Server]
}
self.attribute_map = {
'name': 'name',
'display_name': 'displayName',
'servers': 'servers'
}
self._name = name
self._display_name = display_name
self._servers = servers
@classmethod
def from_dict(cls, dikt) -> 'Room':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The Room of this Room. # noqa: E501
:rtype: Room
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this Room.
:return: The name of this Room.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this Room.
:param name: The name of this Room.
:type name: str
"""
self._name = name
@property
def display_name(self) -> str:
"""Gets the display_name of this Room.
:return: The display_name of this Room.
:rtype: str
"""
return self._display_name
@display_name.setter
def display_name(self, display_name: str):
"""Sets the display_name of this Room.
:param display_name: The display_name of this Room.
:type display_name: str
"""
self._display_name = display_name
@property
def servers(self) -> List[Server]:
"""Gets the servers of this Room.
:return: The servers of this Room.
:rtype: List[Server]
"""
return self._servers
@servers.setter
def servers(self, servers: List[Server]):
"""Sets the servers of this Room.
:param servers: The servers of this Room.
:type servers: List[Server]
"""
self._servers = servers

View File

@@ -0,0 +1,171 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.service import Service
from openapi_server import util
from openapi_server.models.service import Service # noqa: E501
class Server(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, rooms=None, auth_token=None, display_name=None, services=None): # noqa: E501
"""Server - a model defined in OpenAPI
:param name: The name of this Server. # noqa: E501
:type name: str
:param rooms: The rooms of this Server. # noqa: E501
:type rooms: List[str]
:param auth_token: The auth_token of this Server. # noqa: E501
:type auth_token: str
:param display_name: The display_name of this Server. # noqa: E501
:type display_name: str
:param services: The services of this Server. # noqa: E501
:type services: List[Service]
"""
self.openapi_types = {
'name': str,
'rooms': List[str],
'auth_token': str,
'display_name': str,
'services': List[Service]
}
self.attribute_map = {
'name': 'name',
'rooms': 'rooms',
'auth_token': 'authToken',
'display_name': 'displayName',
'services': 'services'
}
self._name = name
self._rooms = rooms
self._auth_token = auth_token
self._display_name = display_name
self._services = services
@classmethod
def from_dict(cls, dikt) -> 'Server':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The Server of this Server. # noqa: E501
:rtype: Server
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this Server.
:return: The name of this Server.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this Server.
:param name: The name of this Server.
:type name: str
"""
self._name = name
@property
def rooms(self) -> List[str]:
"""Gets the rooms of this Server.
Tracks which rooms the server should be listed in; this will not be set when a room is listed to preserve privacy of servers. # noqa: E501
:return: The rooms of this Server.
:rtype: List[str]
"""
return self._rooms
@rooms.setter
def rooms(self, rooms: List[str]):
"""Sets the rooms of this Server.
Tracks which rooms the server should be listed in; this will not be set when a room is listed to preserve privacy of servers. # noqa: E501
:param rooms: The rooms of this Server.
:type rooms: List[str]
"""
self._rooms = rooms
@property
def auth_token(self) -> str:
"""Gets the auth_token of this Server.
Used to authenticate requests which access knocks for this server or attempt to update, delete or create services. In future calls, add a header with the format: Authorization: Bearer <auth_token> # noqa: E501
:return: The auth_token of this Server.
:rtype: str
"""
return self._auth_token
@auth_token.setter
def auth_token(self, auth_token: str):
"""Sets the auth_token of this Server.
Used to authenticate requests which access knocks for this server or attempt to update, delete or create services. In future calls, add a header with the format: Authorization: Bearer <auth_token> # noqa: E501
:param auth_token: The auth_token of this Server.
:type auth_token: str
"""
self._auth_token = auth_token
@property
def display_name(self) -> str:
"""Gets the display_name of this Server.
:return: The display_name of this Server.
:rtype: str
"""
return self._display_name
@display_name.setter
def display_name(self, display_name: str):
"""Sets the display_name of this Server.
:param display_name: The display_name of this Server.
:type display_name: str
"""
self._display_name = display_name
@property
def services(self) -> List[Service]:
"""Gets the services of this Server.
:return: The services of this Server.
:rtype: List[Service]
"""
return self._services
@services.setter
def services(self, services: List[Service]):
"""Sets the services of this Server.
:param services: The services of this Server.
:type services: List[Service]
"""
self._services = services

View File

@@ -0,0 +1,113 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server import util
class Service(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, name=None, protocol=None, version=None): # noqa: E501
"""Service - a model defined in OpenAPI
:param name: The name of this Service. # noqa: E501
:type name: str
:param protocol: The protocol of this Service. # noqa: E501
:type protocol: str
:param version: The version of this Service. # noqa: E501
:type version: str
"""
self.openapi_types = {
'name': str,
'protocol': str,
'version': str
}
self.attribute_map = {
'name': 'name',
'protocol': 'protocol',
'version': 'version'
}
self._name = name
self._protocol = protocol
self._version = version
@classmethod
def from_dict(cls, dikt) -> 'Service':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The Service of this Service. # noqa: E501
:rtype: Service
"""
return util.deserialize_model(dikt, cls)
@property
def name(self) -> str:
"""Gets the name of this Service.
:return: The name of this Service.
:rtype: str
"""
return self._name
@name.setter
def name(self, name: str):
"""Sets the name of this Service.
:param name: The name of this Service.
:type name: str
"""
self._name = name
@property
def protocol(self) -> str:
"""Gets the protocol of this Service.
:return: The protocol of this Service.
:rtype: str
"""
return self._protocol
@protocol.setter
def protocol(self, protocol: str):
"""Sets the protocol of this Service.
:param protocol: The protocol of this Service.
:type protocol: str
"""
self._protocol = protocol
@property
def version(self) -> str:
"""Gets the version of this Service.
:return: The version of this Service.
:rtype: str
"""
return self._version
@version.setter
def version(self, version: str):
"""Sets the version of this Service.
:param version: The version of this Service.
:type version: str
"""
self._version = version

View File

@@ -0,0 +1,121 @@
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from openapi_server.models.base_model import Model
from openapi_server.models.google_protobuf_any import GoogleProtobufAny
from openapi_server import util
from openapi_server.models.google_protobuf_any import GoogleProtobufAny # noqa: E501
class Status(Model):
"""NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Do not edit the class manually.
"""
def __init__(self, code=None, message=None, details=None): # noqa: E501
"""Status - a model defined in OpenAPI
:param code: The code of this Status. # noqa: E501
:type code: int
:param message: The message of this Status. # noqa: E501
:type message: str
:param details: The details of this Status. # noqa: E501
:type details: List[GoogleProtobufAny]
"""
self.openapi_types = {
'code': int,
'message': str,
'details': List[GoogleProtobufAny]
}
self.attribute_map = {
'code': 'code',
'message': 'message',
'details': 'details'
}
self._code = code
self._message = message
self._details = details
@classmethod
def from_dict(cls, dikt) -> 'Status':
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The Status of this Status. # noqa: E501
:rtype: Status
"""
return util.deserialize_model(dikt, cls)
@property
def code(self) -> int:
"""Gets the code of this Status.
The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. # noqa: E501
:return: The code of this Status.
:rtype: int
"""
return self._code
@code.setter
def code(self, code: int):
"""Sets the code of this Status.
The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. # noqa: E501
:param code: The code of this Status.
:type code: int
"""
self._code = code
@property
def message(self) -> str:
"""Gets the message of this Status.
A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. # noqa: E501
:return: The message of this Status.
:rtype: str
"""
return self._message
@message.setter
def message(self, message: str):
"""Sets the message of this Status.
A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. # noqa: E501
:param message: The message of this Status.
:type message: str
"""
self._message = message
@property
def details(self) -> List[GoogleProtobufAny]:
"""Gets the details of this Status.
A list of messages that carry the error details. There is a common set of message types for APIs to use. # noqa: E501
:return: The details of this Status.
:rtype: List[GoogleProtobufAny]
"""
return self._details
@details.setter
def details(self, details: List[GoogleProtobufAny]):
"""Sets the details of this Status.
A list of messages that carry the error details. There is a common set of message types for APIs to use. # noqa: E501
:param details: The details of this Status.
:type details: List[GoogleProtobufAny]
"""
self._details = details

View File

@@ -0,0 +1,658 @@
openapi: 3.0.3
info:
title: PeerNetService API
version: 0.0.1
servers:
- url: /
tags:
- name: PeerNetService
paths:
/v1/rooms/{room}:
get:
operationId: peer_net_service_get_room
parameters:
- description: The room id.
explode: false
in: path
name: room
required: true
schema:
type: string
style: simple
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Room'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers:
post:
operationId: peer_net_service_create_server
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Server'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Server'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers/*:
delete:
operationId: peer_net_service_delete_server
parameters:
- explode: true
in: query
name: name
required: false
schema:
type: string
style: form
responses:
"200":
content: {}
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers/{server}/services:
post:
operationId: peer_net_service_create_service
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Service'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Service'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers/{server}/services/{service}:
delete:
operationId: peer_net_service_delete_service
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
- description: The service id.
explode: false
in: path
name: service
required: true
schema:
type: string
style: simple
responses:
"200":
content: {}
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers/{server}/services/{service}/knocks:
get:
operationId: peer_net_service_list_knocks
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
- description: The service id.
explode: false
in: path
name: service
required: true
schema:
type: string
style: simple
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListKnocksResponse'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
post:
description: |-
Creates a knock that will be answered by the peer; the signaler may
delete the knock, regardless of the state, when it ages.
operationId: peer_net_service_create_knock
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
- description: The service id.
explode: false
in: path
name: service
required: true
schema:
type: string
style: simple
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Knock'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Knock'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/servers/{server}/services/{service}/knocks/{knock}:
get:
operationId: peer_net_service_get_knock
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
- description: The service id.
explode: false
in: path
name: service
required: true
schema:
type: string
style: simple
- description: The knock id.
explode: false
in: path
name: knock
required: true
schema:
type: string
style: simple
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Knock'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
patch:
operationId: peer_net_service_update_knock
parameters:
- description: The server id.
explode: false
in: path
name: server
required: true
schema:
type: string
style: simple
- description: The service id.
explode: false
in: path
name: service
required: true
schema:
type: string
style: simple
- description: The knock id.
explode: false
in: path
name: knock
required: true
schema:
type: string
style: simple
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Knock'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Knock'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/sessions/{session}/candidates:
post:
operationId: peer_net_service_create_ice_candidate
parameters:
- description: The session id.
explode: false
in: path
name: session
required: true
schema:
type: string
style: simple
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/IceCandidate'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/IceCandidate'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
/v1/sessions/{session}/claim/candidates:
get:
description: Acts as both List and Delete atomically.
operationId: peer_net_service_claim_ice_candidates
parameters:
- description: The session id.
explode: false
in: path
name: session
required: true
schema:
type: string
style: simple
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ClaimIceCandidatesResponse'
description: OK
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
description: Default error response
tags:
- PeerNetService
x-openapi-router-controller: openapi_server.controllers.peer_net_service_controller
components:
schemas:
ClaimIceCandidatesResponse:
example:
iceCandidates:
- candidate: candidate
usernameFragment: usernameFragment
name: name
sdpMid: sdpMid
sdpLineIndex: 0
- candidate: candidate
usernameFragment: usernameFragment
name: name
sdpMid: sdpMid
sdpLineIndex: 0
properties:
iceCandidates:
items:
$ref: '#/components/schemas/IceCandidate'
title: iceCandidates
type: array
title: ClaimIceCandidatesResponse
type: object
GoogleProtobufAny:
additionalProperties: true
description: Contains an arbitrary serialized message along with a @type that
describes the type of the serialized message.
example:
'@type': '@type'
properties:
'@type':
description: The type of the serialized message.
type: string
title: GoogleProtobufAny
type: object
IceCandidate:
example:
candidate: candidate
usernameFragment: usernameFragment
name: name
sdpMid: sdpMid
sdpLineIndex: 0
properties:
name:
title: name
type: string
candidate:
title: candidate
type: string
sdpMid:
title: sdpMid
type: string
sdpLineIndex:
format: int32
title: sdpLineIndex
type: integer
usernameFragment:
title: usernameFragment
type: string
title: IceCandidate
type: object
IceSessionDescription:
example:
name: name
sdpType: sdpType
sdp: sdp
properties:
name:
description: |-
A unique identifier which can be used to send ICE candidates
Maps to the session name
title: name
type: string
sdpType:
description: Used to construct the remote description in WebRTC
title: sdpType
type: string
sdp:
title: sdp
type: string
title: IceSessionDescription
type: object
Knock:
example:
offer: ""
answer:
name: name
sdpType: sdpType
sdp: sdp
name: name
properties:
name:
title: name
type: string
offer:
allOf:
- $ref: '#/components/schemas/IceSessionDescription'
description: The service being connected too
title: offer
answer:
$ref: '#/components/schemas/IceSessionDescription'
title: Knock
type: object
ListKnocksResponse:
example:
knocks:
- offer: ""
answer:
name: name
sdpType: sdpType
sdp: sdp
name: name
- offer: ""
answer:
name: name
sdpType: sdpType
sdp: sdp
name: name
properties:
knocks:
items:
$ref: '#/components/schemas/Knock'
title: knocks
type: array
title: ListKnocksResponse
type: object
Room:
example:
servers:
- rooms:
- rooms
- rooms
displayName: displayName
authToken: authToken
name: name
services:
- protocol: protocol
name: name
version: version
- protocol: protocol
name: name
version: version
- rooms:
- rooms
- rooms
displayName: displayName
authToken: authToken
name: name
services:
- protocol: protocol
name: name
version: version
- protocol: protocol
name: name
version: version
displayName: displayName
name: name
properties:
name:
title: name
type: string
displayName:
title: displayName
type: string
servers:
items:
$ref: '#/components/schemas/Server'
title: servers
type: array
title: Room
type: object
Server:
example:
rooms:
- rooms
- rooms
displayName: displayName
authToken: authToken
name: name
services:
- protocol: protocol
name: name
version: version
- protocol: protocol
name: name
version: version
properties:
name:
title: name
type: string
rooms:
description: |-
Tracks which rooms the server should be listed in; this will not
be set when a room is listed to preserve privacy of servers.
items:
type: string
title: rooms
type: array
writeOnly: true
authToken:
description: |-
Used to authenticate requests which access knocks for this server
or attempt to update, delete or create services.
In future calls, add a header with the format:
Authorization: Bearer <auth_token>
title: authToken
type: string
writeOnly: true
displayName:
title: displayName
type: string
services:
items:
$ref: '#/components/schemas/Service'
title: services
type: array
title: Server
type: object
Service:
example:
protocol: protocol
name: name
version: version
properties:
name:
title: name
type: string
protocol:
title: protocol
type: string
version:
title: version
type: string
title: Service
type: object
Status:
description: "The `Status` type defines a logical error model that is suitable\
\ for different programming environments, including REST APIs and RPC APIs.\
\ It is used by [gRPC](https://github.com/grpc). Each `Status` message contains\
\ three pieces of data: error code, error message, and error details. You\
\ can find out more about this error model and how to work with it in the\
\ [API Design Guide](https://cloud.google.com/apis/design/errors)."
example:
code: 0
details:
- '@type': '@type'
- '@type': '@type'
message: message
properties:
code:
description: "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
format: int32
title: code
type: integer
message:
description: "A developer-facing error message, which should be in English.\
\ Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details]\
\ field, or localized by the client."
title: message
type: string
details:
description: A list of messages that carry the error details. There is
a common set of message types for APIs to use.
items:
$ref: '#/components/schemas/GoogleProtobufAny'
title: details
type: array
title: Status
type: object

View File

@@ -0,0 +1,16 @@
import logging
import connexion
from flask_testing import TestCase
from openapi_server.encoder import JSONEncoder
class BaseTestCase(TestCase):
def create_app(self):
logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml', pythonic_params=True)
return app.app

View File

@@ -0,0 +1,200 @@
import unittest
from flask import json
from openapi_server.models.claim_ice_candidates_response import ClaimIceCandidatesResponse # noqa: E501
from openapi_server.models.ice_candidate import IceCandidate # noqa: E501
from openapi_server.models.knock import Knock # noqa: E501
from openapi_server.models.list_knocks_response import ListKnocksResponse # noqa: E501
from openapi_server.models.room import Room # noqa: E501
from openapi_server.models.server import Server # noqa: E501
from openapi_server.models.service import Service # noqa: E501
from openapi_server.models.status import Status # noqa: E501
from openapi_server.test import BaseTestCase
class TestPeerNetServiceController(BaseTestCase):
"""PeerNetServiceController integration test stubs"""
def test_peer_net_service_claim_ice_candidates(self):
"""Test case for peer_net_service_claim_ice_candidates
"""
query_string = [('name', 'name_example')]
headers = {
'Accept': 'application/json',
}
response = self.client.open(
'/v1/sessions/{session}/claim/candidates'.format(session='session_example'),
method='GET',
headers=headers,
query_string=query_string)
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_create_ice_candidate(self):
"""Test case for peer_net_service_create_ice_candidate
"""
ice_candidate = {"candidate":"candidate","usernameFragment":"usernameFragment","sdpMid":"sdpMid","sdpLineIndex":0}
query_string = [('targetSession', 'target_session_example')]
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
response = self.client.open(
'/v1/sessions/{session}/candidates'.format(session='session_example'),
method='POST',
headers=headers,
data=json.dumps(ice_candidate),
content_type='application/json',
query_string=query_string)
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_create_knock(self):
"""Test case for peer_net_service_create_knock
"""
knock = {"offer":{"name":"name","sdpType":"sdpType","sdp":"sdp"},"answer":{"name":"name","sdpType":"sdpType","sdp":"sdp"},"service":"","name":"name"}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
response = self.client.open(
'/v1/servers/{server}/sevices/{sevice}/knocks'.format(server='server_example', sevice='sevice_example'),
method='POST',
headers=headers,
data=json.dumps(knock),
content_type='application/json')
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_create_server(self):
"""Test case for peer_net_service_create_server
"""
server = {"rooms":["rooms","rooms"],"displayName":"displayName","authToken":"authToken","name":"name","services":[{"protocol":"protocol","name":"name","version":"version"},{"protocol":"protocol","name":"name","version":"version"}]}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
response = self.client.open(
'/v1/servers',
method='POST',
headers=headers,
data=json.dumps(server),
content_type='application/json')
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_create_service(self):
"""Test case for peer_net_service_create_service
"""
return
service = {"protocol":"protocol","name":"name","version":"version"}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
response = self.client.open(
'/v1/servers/{server}/services'.format(server='server_example'),
method='POST',
headers=headers,
data=json.dumps(service),
content_type='application/json')
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_delete_server(self):
"""Test case for peer_net_service_delete_server
"""
query_string = [('name', 'name_example')]
headers = {
'Accept': 'application/json',
}
response = self.client.open(
'/v1/servers/*',
method='DELETE',
headers=headers,
query_string=query_string)
self.assert404(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_delete_service(self):
"""Test case for peer_net_service_delete_service
"""
return
headers = {
'Accept': 'application/json',
}
response = self.client.open(
'/v1/servers/{server}/services/{service}'.format(server='server_example', service='service_example'),
method='DELETE',
headers=headers)
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_get_room(self):
"""Test case for peer_net_service_get_room
"""
return
headers = {
'Accept': 'application/json',
}
response = self.client.open(
'/v1/rooms/{room}'.format(room='room_example'),
method='GET',
headers=headers)
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_list_knocks(self):
"""Test case for peer_net_service_list_knocks
"""
headers = {
'Accept': 'application/json',
}
response = self.client.open(
'/v1/servers/{server}/services/{service}/knocks'.format(server='server_example', service='service_example'),
method='GET',
headers=headers)
self.assert401(response,
'Response body is : ' + response.data.decode('utf-8'))
def test_peer_net_service_update_knock(self):
"""Test case for peer_net_service_update_knock
"""
knock2 = {"offer":{"name":"name","sdpType":"sdpType","sdp":"sdp"},"answer":{"name":"name","sdpType":"sdpType","sdp":"sdp"},"service":"","name":"name"}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
response = self.client.open(
'/v1/servers/{server}/services/{service}/knocks/{knock}'.format(server='server_example', service='service_example', knock='knock_example'),
method='PATCH',
headers=headers,
data=json.dumps(knock2),
content_type='application/json')
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,30 @@
import sys
if sys.version_info < (3, 7):
import typing
def is_generic(klass):
""" Determine whether klass is a generic class """
return type(klass) == typing.GenericMeta
def is_dict(klass):
""" Determine whether klass is a Dict """
return klass.__extra__ == dict
def is_list(klass):
""" Determine whether klass is a List """
return klass.__extra__ == list
else:
def is_generic(klass):
""" Determine whether klass is a generic class """
return hasattr(klass, '__origin__')
def is_dict(klass):
""" Determine whether klass is a Dict """
return klass.__origin__ == dict
def is_list(klass):
""" Determine whether klass is a List """
return klass.__origin__ == list

View File

@@ -0,0 +1,147 @@
import datetime
import typing
from openapi_server import typing_utils
def _deserialize(data, klass):
"""Deserializes dict, list, str into an object.
:param data: dict, list or str.
:param klass: class literal, or string of class name.
:return: object.
"""
if data is None:
return None
if klass in (int, float, str, bool, bytearray):
return _deserialize_primitive(data, klass)
elif klass == object:
return _deserialize_object(data)
elif klass == datetime.date:
return deserialize_date(data)
elif klass == datetime.datetime:
return deserialize_datetime(data)
elif typing_utils.is_generic(klass):
if typing_utils.is_list(klass):
return _deserialize_list(data, klass.__args__[0])
if typing_utils.is_dict(klass):
return _deserialize_dict(data, klass.__args__[1])
else:
return deserialize_model(data, klass)
def _deserialize_primitive(data, klass):
"""Deserializes to primitive type.
:param data: data to deserialize.
:param klass: class literal.
:return: int, long, float, str, bool.
:rtype: int | long | float | str | bool
"""
try:
value = klass(data)
except UnicodeEncodeError:
value = data
except TypeError:
value = data
return value
def _deserialize_object(value):
"""Return an original value.
:return: object.
"""
return value
def deserialize_date(string):
"""Deserializes string to date.
:param string: str.
:type string: str
:return: date.
:rtype: date
"""
if string is None:
return None
try:
from dateutil.parser import parse
return parse(string).date()
except ImportError:
return string
def deserialize_datetime(string):
"""Deserializes string to datetime.
The string should be in iso8601 datetime format.
:param string: str.
:type string: str
:return: datetime.
:rtype: datetime
"""
if string is None:
return None
try:
from dateutil.parser import parse
return parse(string)
except ImportError:
return string
def deserialize_model(data, klass):
"""Deserializes list or dict to model.
:param data: dict, list.
:type data: dict | list
:param klass: class literal.
:return: model object.
"""
instance = klass()
if not instance.openapi_types:
return data
for attr, attr_type in instance.openapi_types.items():
if data is not None \
and instance.attribute_map[attr] in data \
and isinstance(data, (list, dict)):
value = data[instance.attribute_map[attr]]
setattr(instance, attr, _deserialize(value, attr_type))
return instance
def _deserialize_list(data, boxed_type):
"""Deserializes a list and its elements.
:param data: list to deserialize.
:type data: list
:param boxed_type: class literal.
:return: deserialized list.
:rtype: list
"""
return [_deserialize(sub_data, boxed_type)
for sub_data in data]
def _deserialize_dict(data, boxed_type):
"""Deserializes a dict and its elements.
:param data: dict to deserialize.
:type data: dict
:param boxed_type: class literal.
:return: deserialized dict.
:rtype: dict
"""
return {k: _deserialize(v, boxed_type)
for k, v in data.items() }

View File

@@ -0,0 +1,13 @@
connexion[swagger-ui] >= 2.6.0; python_version>="3.6"
# 2.3 is the last version that supports python 3.4-3.5
connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4"
# prevent breaking dependencies from advent of connexion>=3.0
connexion[swagger-ui] <= 2.14.2; python_version>"3.4"
# connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug
# we must peg werkzeug versions below to fix connexion
# https://github.com/zalando/connexion/pull/1044
werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4"
swagger-ui-bundle >= 0.0.2
python_dateutil >= 2.6.0
setuptools >= 21.0.0
Flask == 2.1.1

0
demo_server/server.py Normal file
View File

37
demo_server/setup.py Normal file
View File

@@ -0,0 +1,37 @@
import sys
from setuptools import setup, find_packages
NAME = "openapi_server"
VERSION = "1.0.0"
# To install the library, run the following
#
# python setup.py install
#
# prerequisite: setuptools
# http://pypi.python.org/pypi/setuptools
REQUIRES = [
"connexion>=2.0.2",
"swagger-ui-bundle>=0.0.2",
"python_dateutil>=2.6.0"
]
setup(
name=NAME,
version=VERSION,
description="PeerNetService API",
author_email="",
url="",
keywords=["OpenAPI", "PeerNetService API"],
install_requires=REQUIRES,
packages=find_packages(),
package_data={'': ['openapi/openapi.yaml']},
include_package_data=True,
entry_points={
'console_scripts': ['openapi_server=openapi_server.__main__:main']},
long_description="""\
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
"""
)

View File

@@ -0,0 +1,4 @@
pytest~=7.1.0
pytest-cov>=2.8.1
pytest-randomly>=1.2.3
Flask-Testing==0.8.1

94
demo_server/test.sh Executable file
View File

@@ -0,0 +1,94 @@
#!/bin/zsh
curl -X 'POST' \
'http://localhost:8080/v1/servers' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "my server",
"rooms": [
"myroom"
],
"authToken": "string",
"displayName": "Hello",
"services": [
{
"name": "http1",
"protocol": "peernet.http",
"version": "v1"
}
]
}'
curl -X 'GET' \
'http://localhost:8080/v1/rooms/myroom' \
-H 'accept: application/json'
# Simulate a knock
curl -X 'POST' \
'http://127.0.0.1:8080/v1/servers/my%20server/services/http1/knocks' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "knockname",
"offer": {
"name": "name1",
"sdpType": "string",
"sdp": "string"
},
"answer": {
"name": "string",
"sdpType": "string",
"sdp": "string"
}
}'
echo "http://127.0.0.1:8080/v1/servers/my%20server/services/http1/knocks"
curl -X 'GET' \
'http://127.0.0.1:8080/v1/servers/my%20server/services/http1/knocks' \
-H 'accept: application/json'
echo
echo "http://127.0.0.1:8080/v1/servers/my%20server/services/http1/knocks/knockname"
curl -X 'PATCH' \
'http://127.0.0.1:8080/v1/servers/my%20server/services/http1/knocks/knockname' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "knockname",
"offer": {
"name": "name1",
"sdpType": "string",
"sdp": "string"
},
"offer": {
"name": "name1",
"sdpType": "string",
"sdp": "string"
},
"answer": {
"name": "name2",
"sdpType": "name2",
"sdp": "string"
}
}'
curl -X 'POST' \
'http://127.0.0.1:8080/v1/sessions/name2/candidates' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "mycandidate",
"candidate": "string",
"sdpMid": "string",
"sdpLineIndex": 0,
"usernameFragment": "string"
}'
curl -X 'GET' \
'http://127.0.0.1:8080/v1/sessions/name2/claim/candidates' \
-H 'accept: application/json'
curl -X 'GET' \
'http://127.0.0.1:8080/v1/sessions/name2/claim/candidates' \
-H 'accept: application/json'

11
demo_server/tox.ini Normal file
View File

@@ -0,0 +1,11 @@
[tox]
envlist = py3
skipsdist=True
[testenv]
deps=-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
{toxinidir}
commands=
pytest --cov=openapi_server

189
proto/peernet_service.proto Normal file
View File

@@ -0,0 +1,189 @@
syntax = "proto2";
package peernet;
option go_package = "peernet/";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/empty.proto";
service PeerNetService {
rpc GetRoom(GetRoomRequest) returns (Room) {
option (google.api.http) = {
get: "/v1/{name=rooms/*}"
};
};
rpc CreateServer(CreateServerRequest) returns (Server) {
option (google.api.http) = {
post: "/v1/servers"
body: "server"
};
};
rpc DeleteServer(DeleteServerRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
delete: "/v1/servers/*"
};
};
rpc CreateService(CreateServiceRequest) returns (Service) {
option (google.api.http) = {
post: "/v1/{parent=servers/*}/services"
body: "service"
};
};
rpc DeleteService(DeleteServiceRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
delete: "/v1/{name=servers/*/services/*}"
};
};
// Creates a knock that will be answered by the peer; the signaler may
// delete the knock, regardless of the state, when it ages.
rpc CreateKnock(CreateKnockRequest) returns (Knock){
option (google.api.http) = {
post: "/v1/{parent=servers/*/services/*}/knocks"
body: "knock"
};
};
rpc UpdateKnock(UpdateKnockRequest) returns (Knock) {
option (google.api.http) = {
patch: "/v1/{knock.name=servers/*/services/*/knocks/*}"
body: "knock"
};
};
rpc ListKnocks(ListKnocksRequest) returns (ListKnocksResponse) {
option (google.api.http) = {
get: "/v1/{parent=servers/*/services/*}/knocks"
};
};
rpc GetKnock(GetKnockRequest) returns (Knock) {
option (google.api.http) = {
get: "/v1/{name=servers/*/services/*/knocks/*}"
};
};
rpc CreateIceCandidate(CreateIceCandidateRequest) returns (IceCandidate) {
option (google.api.http) = {
post: "/v1/{parent=sessions/*}/candidates"
body: "ice_candidate"
};
};;
// Acts as both List and Delete atomically.
rpc ClaimIceCandidates(ClaimIceCandidatesRequest) returns (ClaimIceCandidatesResponse) {
option (google.api.http) = {
get: "/v1/{parent=sessions/*}/claim/candidates"
};
};
}
message GetKnockRequest {
required string name = 1;
}
message GetRoomRequest {
required string name = 1;
}
message CreateServerRequest {
required Server server = 1 [(google.api.field_behavior) = REQUIRED];
}
message DeleteServerRequest {
required string name = 1;
}
message CreateServiceRequest {
required Service service = 1;
}
message DeleteServiceRequest {
required string name = 1;
}
message CreateKnockRequest {
required Knock knock = 1;
}
message UpdateKnockRequest {
required Knock knock = 1;
}
message ListKnocksRequest { }
message ListKnocksResponse {
repeated Knock knocks = 1;
}
message CreateIceCandidateRequest {
required IceCandidate ice_candidate = 1;
}
message ClaimIceCandidatesRequest { }
message ClaimIceCandidatesResponse {
repeated IceCandidate ice_candidates = 1;
}
message Room {
required string name = 1;
required string display_name = 2;
repeated Server servers = 3;
}
message Server {
required string name = 1;
// Tracks which rooms the server should be listed in; this will not
// be set when a room is listed to preserve privacy of servers.
repeated string rooms = 2 [(google.api.field_behavior) = INPUT_ONLY];
// Used to authenticate requests which access knocks for this server
// or attempt to update, delete or create services.
// In future calls, add a header with the format:
// Authorization: Bearer <auth_token>
required string auth_token = 3 [(google.api.field_behavior) = INPUT_ONLY];
required string display_name = 4;
repeated Service services = 5;
}
message Service {
required string name = 1;
required string protocol = 2;
required string version = 3;
// Used to define custom fields per-protocol/version.
// We use unverified extensions because this system is meant
// to be distributed, with no central owner, hence, no singular
// authority to hand out field numbers. Instead, implementations
// should use the protocol/version to scope what values are expected.
extensions 100 to max [verification = UNVERIFIED];
}
message Knock {
required string name = 1;
// The service being connected too
optional IceSessionDescription offer = 2;
optional IceSessionDescription answer = 3;
}
message IceSessionDescription {
// A unique identifier which can be used to send ICE candidates
// Maps to the session name
required string name = 1;
// Used to construct the remote description in WebRTC
required int64 sdp_type = 3;
required string sdp = 4;
}
message IceCandidate {
required string name = 1;
required string candidate = 2;
optional string sdp_mid = 3;
optional int32 sdp_line_index = 4;
optional string username_fragment = 5;
}