Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stripe-python v8 release #1206

Merged
merged 7 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 3 additions & 2 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# explicitly when using `ignore`.
ignore = E501, W503
per-file-ignores =
*/__init__.py: E402, F401
*/__init__.py: IMP100, E402, F401
# we test various import patterns
tests/test_exports.py: IMP100, IMP101, IMP102
tests/*: IMP101, IMP102, IMP102
tests/*: IMP101, IMP102, BAN100
# backcompat with outdated import patterns
stripe/api_resources/*: IMP100, E402, F401

Expand All @@ -36,4 +36,5 @@ per-file-ignores =
extension =
SPY = flake8_stripe:TypingImportsChecker
IMP = flake8_stripe:StripeImportsChecker
BAN = flake8_stripe:BanPublicMethodsChecker
paths=./flake8_stripe
60 changes: 33 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,18 @@ available in your [Stripe Dashboard][api-keys]. Set `stripe.api_key` to its
value:

```python
import stripe
stripe.api_key = "sk_test_..."
from stripe import StripeClient

client = StripeClient("sk_test_...")

# list customers
customers = stripe.Customer.list()
customers = client.customers.list()

# print the first customer's email
print(customers.data[0].email)

# retrieve specific Customer
customer = stripe.Customer.retrieve("cus_123456789")
customer = client.customers.retrieve("cus_123456789")

# print that customer's email
print(customer.email)
Expand All @@ -75,40 +76,45 @@ these errors.

### Per-request Configuration

Configure individual requests with keyword arguments. For example, you can make
Configure individual requests with the `options` argument. For example, you can make
requests with a specific [Stripe Version](https://stripe.com/docs/api#versioning)
or as a [connected account](https://stripe.com/docs/connect/authentication#authentication-via-the-stripe-account-header):

```python
import stripe
from stripe import StripeClient

client = StripeClient("sk_test_...")

# list customers
stripe.Customer.list(
api_key="sk_test_...",
stripe_account="acct_...",
stripe_version="2019-02-19"
client.customers.list(
options={
"api_key": "sk_test_...",
"stripe_account": "acct_...",
"stripe_version": "2019-02-19",
}
)

# retrieve single customer
stripe.Customer.retrieve(
client.customers.retrieve(
"cus_123456789",
api_key="sk_test_...",
stripe_account="acct_...",
stripe_version="2019-02-19"
options={
"api_key": "sk_test_...",
"stripe_account": "acct_...",
"stripe_version": "2019-02-19",
}
)
```

### Configuring a Client
### Configuring an HTTP Client

The library can be configured to use `urlfetch`, `requests`, `pycurl`, or
`urllib2` with `stripe.default_http_client`:
You can configure your `StripeClient` to use `urlfetch`, `requests`, `pycurl`, or
`urllib2` with the `http_client` option:

```python
client = stripe.http_client.UrlFetchClient()
client = stripe.http_client.RequestsClient()
client = stripe.http_client.PycurlClient()
client = stripe.http_client.Urllib2Client()
stripe.default_http_client = client
client = StripeClient("sk_test_...", http_client=stripe.UrlFetchClient())
client = StripeClient("sk_test_...", http_client=stripe.RequestsClient())
client = StripeClient("sk_test_...", http_client=stripe.PycurlClient())
client = StripeClient("sk_test_...", http_client=stripe.Urllib2Client())
```

Without a configured client, by default the library will attempt to load
Expand All @@ -117,10 +123,10 @@ as a last resort). We usually recommend that people use `requests`.

### Configuring a Proxy

A proxy can be configured with `stripe.proxy`:
A proxy can be configured with the `proxy` client option:

```python
stripe.proxy = "https://user:pass@example.com:1234"
client = StripeClient("sk_test_...", proxy="https://user:pass@example.com:1234")
```

### Configuring Automatic Retries
Expand All @@ -129,7 +135,7 @@ You can enable automatic retries on requests that fail due to a transient
problem by configuring the maximum number of retries:

```python
stripe.max_network_retries = 2
client = StripeClient("sk_test_...", max_network_retries=2)
```

Various errors can trigger a retry, like a connection error or a timeout, and
Expand Down Expand Up @@ -172,7 +178,7 @@ There are a few options for enabling it:
You can access the HTTP response code and headers using the `last_response` property of the returned resource.

```python
customer = stripe.Customer.retrieve(
customer = client.customers.retrieve(
"cus_123456789"
)

Expand Down Expand Up @@ -233,7 +239,7 @@ in your `requirements.txt` to constrain `pip` to a certain minor range of `strip

The types describe the [Stripe API version](https://stripe.com/docs/api/versioning)
that was the latest at the time of release. This is the version that your library
sends by default. If you are overriding `stripe.api_version`, or using a
sends by default. If you are overriding `stripe.api_version` / `stripe_version` on the `StripeClient`, or using a
[webhook endpoint](https://stripe.com/docs/webhooks#api-versions) tied to an older version,
be aware that the data you see at runtime may not match the types.

Expand Down
48 changes: 48 additions & 0 deletions flake8_stripe/flake8_stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class TypingImportsChecker:
allowed_typing_extensions_imports = [
"Literal",
"NoReturn",
"NotRequired",
"Protocol",
"Self",
"TYPE_CHECKING",
"Type",
"TypedDict",
Expand Down Expand Up @@ -173,3 +175,49 @@ def run(self) -> Iterator[Tuple[int, int, str, type]]:
msg,
type(self),
)


class BanPublicMethodsChecker:
name = __name__
version = "0.1.0"

def __init__(self, tree: ast.AST, filename: str):
self.tree = tree
self.filename = filename

def run(self) -> Iterator[Tuple[int, int, str, type]]:
for node in ast.walk(self.tree):
if isinstance(node, ast.Call):
name = None
if isinstance(node.func, ast.Attribute):
name = node.func.attr
elif isinstance(node.func, ast.Name):
name = node.func.id

if not name:
continue

if name == "convert_to_stripe_object":
msg = "BAN100 Do not use public `convert_to_stripe_object` internally. Instead, call `_convert_to_stripe_object` directly."
yield (
node.lineno,
node.col_offset,
msg,
type(self),
)
if name == "construct_from":
msg = "BAN100 Do not use public `construct_from` internally. Instead, call `_construct_from` directly."
yield (
node.lineno,
node.col_offset,
msg,
type(self),
)
if name == "refresh_from":
msg = "BAN100 Do not use public `refresh_from` internally. Instead, call `_refresh_from` directly."
yield (
node.lineno,
node.col_offset,
msg,
type(self),
)
Loading
Loading