Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Commit

Permalink
Ustream v1.12.6 updates added to async clients (#15)
Browse files Browse the repository at this point in the history
Async client now supports the following changes from upstream sync client:

* Add support for query_all in bulk2
* Pass through params in api get
* Allow Non-Standard Domain in JWT for GovCloud
* Add type annotations

In addition, we have fixed a major bug with the async metadata client which would have left various functionalities in those clients broken (missing `address` for ServiceProxy). 

Finally, this PR has also pulled the `tests` directory _out_ of the package, instead of shipping it with the library.
  • Loading branch information
erewok authored Jul 29, 2024
1 parent 4ee861c commit feca2e5
Show file tree
Hide file tree
Showing 29 changed files with 1,498 additions and 598 deletions.
43 changes: 42 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ on:
pull_request:
branches:
- master
- main
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'

jobs:
tests:
env:
COVERAGE_DIR: ${{ format('/tmp/coverage/{0}', github.run_id) }}
permissions:
checks: write
contents: read
pull-requests: write

name: "Python ${{ matrix.python-version }}"
runs-on: "ubuntu-latest"
strategy:
Expand All @@ -34,4 +43,36 @@ jobs:
- name: "Run poetry install deps"
run: "poetry install --no-root"
- name: "Run tests"
run: "poetry run pytest"
run: "poetry run pytest --cov-report xml --junitxml=${COVERAGE_DIR}/unittest.junit.xml"

# - name: "Run mypy"
# run: "poetry run mypy simple_salesforce/aio"

# Publish code coverage results
- name: Code Coverage Report
if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest' }}
uses: irongut/[email protected]
with:
filename: coverage.xml
badge: true
fail_below_min: true
format: markdown
hide_branch_rate: false
hide_complexity: true
indicators: true
output: both
thresholds: '70 80'

- name: Add Coverage PR Comment
if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest' }}
uses: marocchino/sticky-pull-request-comment@v2
with:
recreate: true
path: code-coverage-results.md

# Publish junit test result
- name: Publish Test Report
if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest' }}
uses: mikepenz/action-junit-report@v4
with:
report_paths: ${{ format('/tmp/coverage/{0}/*junit.xml', github.run_id) }}
74 changes: 73 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ zeep = "<5"
[tool.poetry.group.dev.dependencies]
black = "^23.7.0"
cryptography = "*"
mypy = "^1.11.0"
pylint = "^2.17.5"
pytest = "^7.4.0"
pytest-asyncio = "^0.21.1"
Expand All @@ -32,6 +33,8 @@ pytest-pylint = "^0.19.0"
pytz = "^2023.3"
responses = "^0.23.3"
twine = "^3.8.0"
types-aiofiles = "^24.1.0.20240626"
types-requests = "^2.32.0.20240712"

[build-system]
requires = ["poetry-core"]
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
'pytz>=2014.1.1',
'responses>=0.5.1',
],
test_suite='simple_salesforce.tests',
test_suite='tests',
keywords=about['__keywords__'],
classifiers=[
'Development Status :: 5 - Production/Stable',
Expand Down
8 changes: 8 additions & 0 deletions simple_salesforce/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@
from .api import build_async_salesforce_client, AsyncSalesforce, AsyncSFType
from .bulk import AsyncSFBulkHandler
from .login import AsyncSalesforceLogin

__all__ = [
"build_async_salesforce_client",
"AsyncSalesforce",
"AsyncSFType",
"AsyncSFBulkHandler",
"AsyncSalesforceLogin",
]
54 changes: 48 additions & 6 deletions simple_salesforce/aio/aio_util.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
"""Utility functions for simple-salesforce async calls"""

from functools import partial
from typing import Callable, Dict, Optional
from typing import Any, AsyncIterable, Callable, List, NoReturn, Optional, TypeVar

import httpx

from simple_salesforce.util import exception_handler
from simple_salesforce.exceptions import (
SalesforceExpiredSession,
SalesforceGeneralError,
SalesforceMalformedRequest,
SalesforceMoreThanOneRecord,
SalesforceRefusedRequest,
SalesforceResourceNotFound,
)
from simple_salesforce.util import Headers, Proxies


T = TypeVar('T')


def create_session_factory(
proxies=None, timeout: Optional[int] = None
proxies: Proxies | None = None, timeout: Optional[int] = None
) -> Callable[[], httpx.AsyncClient]:
"""
Convenience function for repeatedly returning the properly constructed
Expand All @@ -27,10 +39,10 @@ def create_session_factory(
async def call_salesforce(
url: str = "",
method: str = "GET",
headers: Optional[Dict] = None,
headers: Optional[Headers] = None,
session_factory: Optional[Callable[[], httpx.AsyncClient]] = None,
**kwargs
):
**kwargs: Any,
) -> httpx.Response:
"""Utility method for performing HTTP call to Salesforce.
Returns a `httpx.Response` object.
Expand All @@ -50,3 +62,33 @@ async def call_salesforce(
exception_handler(result)

return result


def exception_handler(result: httpx.Response, name: str = "") -> NoReturn:
"""Exception router. Determines which error to raise for bad results"""
try:
response_content = result.json()
# pylint: disable=broad-except
except Exception:
response_content = result.text

exc_map = {
300: SalesforceMoreThanOneRecord,
400: SalesforceMalformedRequest,
401: SalesforceExpiredSession,
403: SalesforceRefusedRequest,
404: SalesforceResourceNotFound,
}
exc_cls = exc_map.get(result.status_code, SalesforceGeneralError)

raise exc_cls(str(result.url), result.status_code, name, response_content)


async def alist_from_generator(
generator_function: AsyncIterable[List[T]]
) -> List[T]:
"""Utility method for constructing a list from a generator function"""
ret_val: List[T] = []
async for list_results in generator_function:
ret_val.extend(list_results)
return ret_val
Loading

0 comments on commit feca2e5

Please sign in to comment.