Skip to content

Commit

Permalink
Initial rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
ChemicalLuck committed May 1, 2024
1 parent 8cb1ddb commit 760991f
Show file tree
Hide file tree
Showing 25 changed files with 2,189 additions and 542 deletions.
10 changes: 3 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
*.pyc
/.ruff_cache
__pycache__
.vscode
venv
.idea
dist/*
recharge_api.egg-info
recharge-api.toml
/.venv
/*.egg-info
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
13 changes: 13 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
alias l := lock
alias i := install
alias u := uninstall
alias c := clean

lock:
uv pip freeze | uv pip compile - -o requirements.txt
install:
uv pip install -e .
uninstall:
uv pip uninstall qrgenerator
clean:
rm -rf *.egg-info .ruff_cache
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools >= 48"]
build-backend = "setuptools.build_meta"
69 changes: 38 additions & 31 deletions recharge/__init__.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
from .resources import (
RechargeAddress,
RechargeCharge,
RechargeCheckout,
RechargeCustomer,
RechargeOrder,
RechargeSubscription,
RechargeOnetime,
RechargeDiscount,
RechargeWebhook,
RechargeMetafield,
RechargeShop,
RechargeProduct
)
from recharge.api.notifications import NotificationResource
from recharge.api.addresses import AddressResource
from recharge.api.charges import ChargeResource
from recharge.api.checkouts import CheckoutResource
from recharge.api.customers import CustomerResource
from recharge.api.orders import OrderResource
from recharge.api.subscriptions import SubscriptionResource
from recharge.api.onetimes import OnetimeResource
from recharge.api.discounts import DiscountResource
from recharge.api.webhooks import WebhookResource
from recharge.api.metafields import MetafieldResource
from recharge.api.shop import ShopResource
from recharge.api.products import ProductResource
from recharge.api.async_batches import AsyncBatchResource
from recharge.api.tokens import TokenResource


class RechargeAPI(object):

def __init__(self, access_token=None, log_debug=False):
def __init__(self, access_token=None, debug=False):
self.access_token = access_token
self.log_debug = log_debug
self.debug = debug

kwargs = {
'access_token': access_token,
'log_debug': log_debug,
"access_token": access_token,
"log_debug": debug,
}

self.Address = RechargeAddress(**kwargs)
self.Charge = RechargeCharge(**kwargs)
self.Checkout = RechargeCheckout(**kwargs)
self.Customer = RechargeCustomer(**kwargs)
self.Order = RechargeOrder(**kwargs)
self.Subscription = RechargeSubscription(**kwargs)
self.Onetime = RechargeOnetime(**kwargs)
self.Discount = RechargeDiscount(**kwargs)
self.Webhook = RechargeWebhook(**kwargs)
self.Metafield = RechargeMetafield(**kwargs)
self.Shop = RechargeShop(**kwargs)
self.Product = RechargeProduct(**kwargs)
self.Token = TokenResource(**kwargs)
self.scopes = self.Token.get()["scopes"]

kwargs["scopes"] = self.scopes

self.Address = AddressResource(**kwargs)
self.Charge = ChargeResource(**kwargs)
self.Checkout = CheckoutResource(**kwargs)
self.Customer = CustomerResource(**kwargs)
self.Order = OrderResource(**kwargs)
self.Subscription = SubscriptionResource(**kwargs)
self.Onetime = OnetimeResource(**kwargs)
self.Discount = DiscountResource(**kwargs)
self.Webhook = WebhookResource(**kwargs)
self.Metafield = MetafieldResource(**kwargs)
self.Shop = ShopResource(**kwargs)
self.Product = ProductResource(**kwargs)
self.AsyncBatch = AsyncBatchResource(**kwargs)
self.Notification = NotificationResource(**kwargs)
104 changes: 104 additions & 0 deletions recharge/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import logging
import time
from typing import Any, Mapping

import requests

from recharge.api.tokens import TokenScope

log = logging.getLogger(__name__)


class RechargeResource(object):
"""
Resource from the Recharge API. This class handles
logging, sending requests, parsing JSON, and rate
limiting.
Refer to the API docs to see the expected responses.
https://developer.rechargepayments.com/
"""

base_url = "https://api.rechargeapps.com"
object_list_key = None

def __init__(
self, access_token=None, debug=False, scopes: list[TokenScope] | None = None
):
self.debug = debug
self.headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"X-Recharge-Access-Token": access_token,
}
self.scopes = scopes
self.allowed_endpoints = []

def check_scopes(self, endpoint: str, scopes: list[TokenScope]):
if endpoint in self.allowed_endpoints:
return

if not self.scopes:
raise ValueError("No scopes found for token.")

missing_scopes = []

for scope in scopes:
if scope not in self.scopes:
missing_scopes.append(scope)

if missing_scopes:
raise ValueError(f"Endpoint {endpoint} missing scopes: {missing_scopes}")
else:
self.allowed_endpoints.append(endpoint)

def log(self, url, response):
if self.debug:
log.info(url)
log.info(response.headers["X-Recharge-Limit"])

@property
def url(self) -> str:
return f"{self.base_url}/{self.object_list_key}"

def http_delete(self, url: str, body: Mapping[str, Any] | None = None):
response = requests.delete(url, headers=self.headers, json=body)
log.info(url)
log.info(response.headers["X-Recharge-Limit"])
if response.status_code == 429:
return self.http_delete(url)
return response

def http_get(self, url: str, query: Mapping[str, Any] | None = None):
response = requests.get(url, params=query, headers=self.headers)
self.log(url, response)
if response.status_code == 429:
time.sleep(1)
return self.http_get(url)
return response.json()

def http_put(
self,
url: str,
body: Mapping[str, Any] | None = None,
query: Mapping[str, Any] | None = None,
):
response = requests.put(url, json=body, params=query, headers=self.headers)
self.log(url, response)
if response.status_code == 429:
time.sleep(1)
return self.http_put(url, body)
return response.json()

def http_post(
self,
url: str,
body: Mapping[str, Any] | None = None,
query: Mapping[str, Any] | None = None,
):
response = requests.post(url, json=body, params=query, headers=self.headers)
self.log(url, response)
if response.status_code == 429:
time.sleep(1)
return self.http_post(url, body)
return response.json()
Loading

0 comments on commit 760991f

Please sign in to comment.