Skip to content

Commit b1a5aab

Browse files
committed
Move package under picketapi
1 parent 72c3b94 commit b1a5aab

File tree

7 files changed

+352
-76
lines changed

7 files changed

+352
-76
lines changed

poetry.lock

Lines changed: 257 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@ version = "0.1.0"
44
description = "The official Python library for the Picket API (https://picketapi.com/)"
55
authors = ["Devin Stein <[email protected]>"]
66
readme = "README.md"
7+
packages = [
8+
{ include = "picketapi", from = "src" },
9+
]
710

811
[tool.poetry.dependencies]
9-
python = "^3.10"
12+
python = "^3.7"
1013
requests = "^2.28.1"
1114

1215

1316
[tool.poetry.group.dev.dependencies]
1417
black = "^22.10.0"
18+
pytest = "^7.2.0"
19+
responses = "^0.22.0"
1520

1621
[build-system]
1722
requires = ["poetry-core"]

src/picketapi/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# expose Picket as a top-level import
2+
from .picket import *

src/picketapi/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class PicketAPIException(Exception):
2+
def __init__(self, msg: str, code: str):
3+
super().__init__(msg)
4+
self.msg = msg
5+
self.code = code
6+
7+
def __str__(self):
8+
return self.msg

src/picketapi/helpers.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def is_successful_status_code(status_code: int) -> bool:
2+
return status_code >= 200 and status_code < 300
3+
4+
5+
def snake_to_camel(name: str) -> str:
6+
parts = name.split("_")
7+
return "".join(word if idx == 0 else word.title() for idx, word in enumerate(parts))
8+
9+
10+
def snake_to_camel_keys(d: dict) -> dict:
11+
return {snake_to_camel(k): v for k, v in d.items()}

src/picket.py renamed to src/picketapi/picket.py

Lines changed: 17 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,22 @@
11
import os
22

3-
from dataclasses import dataclass
4-
from typing import Dict
5-
63
import requests
74
from requests.auth import HTTPBasicAuth
85
from requests.exceptions import JSONDecodeError
96

7+
from .exceptions import PicketAPIException
8+
from .helpers import is_successful_status_code, snake_to_camel_keys
9+
from .types import (
10+
NonceResponse,
11+
AuthorizedUser,
12+
AuthResponse,
13+
TokenOwnershipResponse,
14+
)
15+
1016
API_VERSION = "v1"
1117
API_BASE_URL = os.path.join("https://picketapi.com/api/", API_VERSION)
1218

1319

14-
def is_successful_status_code(status_code):
15-
return status_code >= 200 and status_code < 300
16-
17-
18-
class PicketAPIException(Exception):
19-
def __init__(self, msg: str, code: str):
20-
super().__init__(msg)
21-
self.msg = msg
22-
self.code = code
23-
24-
def __str__(self):
25-
return self.msg
26-
27-
28-
@dataclass
29-
class NonceResponse:
30-
nonce: str
31-
statement: str
32-
format: str
33-
34-
@classmethod
35-
def from_dict(cls, d):
36-
return cls(d["nonce"], d["statement"], d["format"])
37-
38-
39-
TokenBalances = Dict[str, Dict[str, str]]
40-
41-
42-
@dataclass
43-
class AuthorizedUser:
44-
chain: str
45-
wallet_address: str
46-
display_name: str
47-
token_balances: TokenBalances
48-
49-
@classmethod
50-
def from_dict(cls, d):
51-
return cls(
52-
d["chain"], d["wallet_address"], d["display_name"], d["token_balances"]
53-
)
54-
55-
56-
@dataclass
57-
class AuthResponse:
58-
access_token: str
59-
user: AuthorizedUser
60-
61-
@classmethod
62-
def from_dict(cls, d):
63-
user = AuthorizedUser.from_dict(d["user"])
64-
return cls(d["accessToken"], user)
65-
66-
67-
@dataclass
68-
class TokenOwnershipResponse:
69-
allowed: bool
70-
walletAddress: str
71-
token_balances: TokenBalances
72-
73-
@classmethod
74-
def from_dict(cls, d):
75-
return cls(d["allowed"], d["walletAddress"], d["token_balances"])
76-
77-
7820
class Picket:
7921
def __init__(self, api_key: str, **kwargs):
8022
self.api_key = api_key
@@ -93,14 +35,20 @@ def post_request(self, path: str, **kwargs):
9335
auth = HTTPBasicAuth(self.api_key, "")
9436
headers = self.headers()
9537

96-
req = requests.post(url, auth=auth, headers=headers, data=kwargs)
38+
# transform keys to camelCase
39+
req = requests.post(
40+
url, auth=auth, headers=headers, json=snake_to_camel_keys(kwargs)
41+
)
9742
try:
9843
data = req.json()
9944
except JSONDecodeError:
10045
raise Exception(req.text)
10146

10247
if not is_successful_status_code(req.status_code):
103-
raise PicketAPIException(data["msg"], data["code"])
48+
if "msg" not in data:
49+
raise Exception(data)
50+
# msg is required, code is optional
51+
raise PicketAPIException(data["msg"], data.get("code", None))
10452

10553
return data
10654

src/picketapi/types.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from dataclasses import dataclass
2+
from typing import Dict
3+
4+
5+
@dataclass
6+
class NonceResponse:
7+
nonce: str
8+
statement: str
9+
format: str
10+
11+
@classmethod
12+
def from_dict(cls, d):
13+
return cls(d["nonce"], d["statement"], d["format"])
14+
15+
16+
TokenBalances = Dict[str, Dict[str, str]]
17+
18+
19+
@dataclass
20+
class AuthorizedUser:
21+
chain: str
22+
wallet_address: str
23+
display_address: str
24+
token_balances: TokenBalances
25+
26+
@classmethod
27+
def from_dict(cls, d):
28+
return cls(
29+
d["chain"], d["walletAddress"], d["displayAddress"], d["tokenBalances"]
30+
)
31+
32+
33+
@dataclass
34+
class AuthResponse:
35+
access_token: str
36+
user: AuthorizedUser
37+
38+
@classmethod
39+
def from_dict(cls, d):
40+
user = AuthorizedUser.from_dict(d["user"])
41+
return cls(d["accessToken"], user)
42+
43+
44+
@dataclass
45+
class TokenOwnershipResponse:
46+
allowed: bool
47+
token_balances: TokenBalances
48+
49+
@classmethod
50+
def from_dict(cls, d):
51+
return cls(d["allowed"], d["tokenBalances"])

0 commit comments

Comments
 (0)