Skip to content

Commit 5ec4c21

Browse files
committed
Implemented CPython version
1 parent 759788f commit 5ec4c21

File tree

5 files changed

+464
-66
lines changed

5 files changed

+464
-66
lines changed

servercom/__init__.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""The API wrapper for sending data to the CubeServer server
2+
See https://github.com/snorklerjoe/CubeServer-api-circuitpython for more info!
3+
4+
Supported implementations: cpython, circuitpython
5+
"""
6+
7+
from sys import implementation as _implementation
8+
9+
10+
# Check the implementation to use
11+
if _implementation.name == 'circuitpython':
12+
# Use the CircuitPython version:
13+
from .implementations.circuitpy import *
14+
elif _implementation.name == 'cpython':
15+
# Use the CPython version:
16+
from .implementations.cpy import *
17+
elif _implementation.name == 'micropython':
18+
raise NotImplementedError(
19+
"Unfortunately there is not yet a MicroPython implementation of this "
20+
"library and it seems rather unlikely that there ever will be.\n"
21+
"Perhaps you would like to look into adapting the CircuitPython "
22+
"implementation for this purpose or simply using CircuitPython "
23+
"to begin with?"
24+
)
25+
else:
26+
# Uh oh, we don't support this platform!
27+
raise NotImplementedError(
28+
f"This library is not supported for the {_implementation.name} "
29+
"implementation of Python.\n"
30+
"We do, however, support CircuitPython and CPython."
31+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""The Implementations of the Python API Wrapper
2+
3+
These are separate implementations of the API wrapper which generally serve
4+
the same purpose, but are meant to run on different hardware or to be used
5+
in different situations.
6+
"""

server.py renamed to servercom/implementations/circuitpy.py

Lines changed: 32 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1-
"""The API wrapper for sending data to the CubeServer server
2-
See https://github.com/snorklerjoe/CubeServer-api-circuitpython for more info!
3-
"""
1+
"""CircuitPython implementation of the CubeServer API Wrapper Library"""
2+
3+
from .common import *
44

55
import ssl
66
import wifi
77
import socketpool
88
from gc import collect
9-
from collections import namedtuple
10-
from binascii import b2a_base64
119
from errno import EAGAIN
12-
from json import loads, dumps
13-
14-
try:
15-
import client_config
16-
except ImportError:
17-
pass
18-
10+
from binascii import b2a_base64
11+
from json import loads
1912

2013
# Helpers:
21-
DEGREE_SIGN = u"\xb0"
22-
2314
def enum(**enums):
2415
"""Fake enum-maker"""
2516
return type('Enum', (), enums)
@@ -28,25 +19,6 @@ def basic_auth_str(user: str, pwd: str) -> str:
2819
"""Encodes the username and password as per RFC7617 on Basic Auth"""
2920
return b2a_base64(f"{user}:{pwd}".encode()).strip().decode("utf-8")
3021

31-
def urlencode(stuff: str) -> str:
32-
"""URL-encodes a string"""
33-
output = ""
34-
for char in stuff:
35-
if char.isalpha() or char.isdigit():
36-
output += char
37-
else:
38-
hex_repr = hex(ord(char)).lstrip('0x').upper()
39-
if ord(char) <= 0xFF:
40-
output += '%' + hex_repr
41-
elif 0xFF < ord(char) <= 0xFFFF:
42-
if len(hex_repr) == 3:
43-
hex_repr = '0' + hex_repr
44-
output += '%' + hex_repr[:2] + '%' + hex_repr[2:]
45-
else:
46-
raise ValueError("Unencodable character")
47-
48-
return output
49-
5022

5123
DataClass = enum(
5224
TEMPERATURE = "temperature",
@@ -118,46 +90,33 @@ class ConnectionError(Exception):
11890
class AuthorizationError(ConnectionError):
11991
"""Indicates an issue with the team credentials"""
12092

121-
class ConnectionConfig:
122-
"""The configuration of the connection to the server"""
123-
TIMEOUT: int = 60
124-
if 'client_config' in globals():
125-
AP_SSID: str = client_config.CONF_AP_SSID
126-
API_CN: str = client_config.CONF_API_CN
127-
API_HOST: str = client_config.CONF_API_HOST
128-
API_PORT: int = client_config.API_PORT
129-
else:
130-
AP_SSID: str = "CubeServer-API"
131-
API_CN: str = "api.local"
132-
API_HOST: str = "https://api.local"
133-
API_PORT: int = 8081
134-
135-
CUBESERVER_DEFAULT_CONFIG = ConnectionConfig()
136-
137-
GameStatus = namedtuple("GameStatus",
138-
['unix_time',
139-
'score',
140-
'strikes']
141-
)
142-
143-
HTTPResponse = namedtuple("HTTPResponse",
144-
['code', 'body']
145-
)
93+
def urlencode(stuff: str) -> str:
94+
"""URL-encodes a string"""
95+
output = ""
96+
for char in stuff:
97+
if char.isalpha() or char.isdigit():
98+
output += char
99+
else:
100+
hex_repr = hex(ord(char)).lstrip('0x').upper()
101+
if ord(char) <= 0xFF:
102+
output += '%' + hex_repr
103+
elif 0xFF < ord(char) <= 0xFFFF:
104+
if len(hex_repr) == 3:
105+
hex_repr = '0' + hex_repr
106+
output += '%' + hex_repr[:2] + '%' + hex_repr[2:]
107+
else:
108+
raise ValueError("Unencodable character")
146109

147-
def _if_conf_exists(key: str):
148-
"""Returns the config value if client_config is imported, else None"""
149-
if 'client_config' not in globals():
150-
return None
151-
return getattr(client_config, key)
110+
return output
152111

153112
class Connection:
154113
"""A class for connecting to the server"""
155114

156115
def __init__(
157116
self,
158-
team_name: str = _if_conf_exists('TEAM_NAME'),
159-
team_secret: str = _if_conf_exists('TEAM_SECRET'),
160-
server_cert: str = _if_conf_exists('SERVER_CERT'),
117+
team_name: str = conf_if_exists('TEAM_NAME'),
118+
team_secret: str = conf_if_exists('TEAM_SECRET'),
119+
server_cert: str = conf_if_exists('SERVER_CERT'),
161120
conf = CUBESERVER_DEFAULT_CONFIG,
162121
verbose: bool = False,
163122
_force: bool = False,
@@ -172,6 +131,7 @@ def __init__(
172131
) or \
173132
not isinstance(conf, ConnectionConfig):
174133
raise TypeError("Bad parameters or client config")
134+
175135
self.team_name = team_name
176136
self.team_secret = team_secret
177137
self.server_cert = server_cert
@@ -401,3 +361,9 @@ def post(self, point: DataPoint) -> bool:
401361
content_type = 'application/json',
402362
headers=['User-Agent: Dude']
403363
).code == 201
364+
365+
def __exit__(self):
366+
if self.v:
367+
print("Closing the server connection-")
368+
self.close_socket()
369+
self.close_wifi()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Helpers, interfaces, etc. common to ALL implementations"""
2+
3+
print("Common")
4+
5+
# Try to import configuration file
6+
try:
7+
import client_config
8+
except ImportError:
9+
pass
10+
11+
from collections import namedtuple
12+
13+
14+
# Constants:
15+
DEGREE_SIGN = u"\xb0"
16+
17+
18+
GameStatus = namedtuple("GameStatus",
19+
['unix_time',
20+
'score',
21+
'strikes']
22+
)
23+
24+
HTTPResponse = namedtuple("HTTPResponse",
25+
['code', 'body']
26+
)
27+
28+
def conf_if_exists(key: str):
29+
"""Returns the config value if client_config is imported, else None"""
30+
if 'client_config' not in globals():
31+
return None
32+
return getattr(client_config, key)
33+
34+
class ConnectionConfig:
35+
"""The configuration of the connection to the server"""
36+
TIMEOUT: int = 60
37+
if 'client_config' in globals():
38+
AP_SSID: str = client_config.CONF_AP_SSID
39+
API_CN: str = client_config.CONF_API_CN
40+
API_HOST: str = client_config.CONF_API_HOST
41+
API_PORT: int = client_config.API_PORT
42+
else:
43+
AP_SSID: str = "CubeServer-API"
44+
API_CN: str = "api.local"
45+
API_HOST: str = "https://api.local"
46+
API_PORT: int = 8081
47+
48+
CUBESERVER_DEFAULT_CONFIG = ConnectionConfig()

0 commit comments

Comments
 (0)