Skip to content

Commit

Permalink
release(python-sdk): v0.5.0 (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
evansims committed Jun 17, 2024
2 parents 7db1b4f + 3095e2a commit fd85d01
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 265 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ build-client-python:
make run-in-docker sdk_language=python image=busybox:${BUSYBOX_DOCKER_TAG} command="/bin/sh -c 'patch -p1 /module/openfga_sdk/api/open_fga_api.py /config/clients/python/patches/open_fga_api.py.patch'"
make run-in-docker sdk_language=python image=busybox:${BUSYBOX_DOCKER_TAG} command="/bin/sh -c 'patch -p1 /module/openfga_sdk/sync/open_fga_api.py /config/clients/python/patches/open_fga_api_sync.py.patch'"
make run-in-docker sdk_language=python image=busybox:${BUSYBOX_DOCKER_TAG} command="/bin/sh -c 'patch -p1 /module/docs/OpenFgaApi.md /config/clients/python/patches/OpenFgaApi.md.patch'"
make run-in-docker sdk_language=python image=python:${PYTHON_DOCKER_TAG} command="/bin/sh -c 'python -m pip install pyupgrade==3.15.1 isort==5.13.2 black==24.2.0 autoflake==2.3.0; pyupgrade \`find . -name *.py -type f\` --py310-plus --keep-runtime-typing; isort . --profile black; black .; autoflake --exclude=__init__.py --in-place --remove-unused-variables --remove-all-unused-imports -r .'"
make run-in-docker sdk_language=python image=python:${PYTHON_DOCKER_TAG} command="/bin/sh -c 'python -m pip install pyupgrade==3.15.2 isort==5.13.2 black==24.4.2 autoflake==2.3.1; pyupgrade \`find . -name *.py -type f\` --py310-plus --keep-runtime-typing; isort . --profile black; autoflake --exclude=__init__.py --in-place --remove-unused-variables --remove-all-unused-imports -r .; black .'"
make run-in-docker sdk_language=python image=python:${PYTHON_DOCKER_TAG} command="/bin/sh -c 'pip install setuptools wheel && python setup.py sdist bdist_wheel'"

.PHONY: test-client-python
Expand Down
9 changes: 9 additions & 0 deletions config/clients/python/CHANGELOG.md.mustache
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## v0.5.0

### [0.5.0](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.4.2...v0.5.0) (2024-06-17)

- fix: ClientTuple condition property type
- fix: list_users should accept FgaObject type
- fix: remove ReadAuthorizationModel calls from BatchCheck and writes
- chore!: remove excluded users from ListUsers response

## v0.4.3

### [0.4.3](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.4.2...v0.4.3) (2024-06-07)
Expand Down
2 changes: 1 addition & 1 deletion config/clients/python/config.overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"sdkId": "python",
"gitRepoId": "python-sdk",
"packageName": "openfga_sdk",
"packageVersion": "0.4.3",
"packageVersion": "0.5.0",
"packageDescription": "Python SDK for OpenFGA",
"packageDetailedDescription": "This is an autogenerated python SDK for OpenFGA. It provides a wrapper around the [OpenFGA API definition](https://openfga.dev/api).",
"fossaComplianceNoticeId": "2f8a8629-b46c-435e-b8cd-1174a674fb4b",
Expand Down
8 changes: 8 additions & 0 deletions config/clients/python/template/.github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ updates:
- "*"
ignore:
- dependency-name: "urllib3"
- package-ecosystem: "pip"
directory: "/example/example1"
schedule:
interval: "monthly"
groups:
dependencies:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 0

Expand Down Expand Up @@ -60,7 +60,7 @@ jobs:

- if: matrix.python-version == '3.10'
name: Upload coverage to Codecov
uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # v4.3.0
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
continue-on-error: true
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand All @@ -75,7 +75,7 @@ jobs:
id-token: write # Required for PyPI trusted publishing

steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 0

Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:
needs: [publish]

steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 0

Expand Down
3 changes: 2 additions & 1 deletion config/clients/python/template/README_calling_api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ List the users who have a certain relation to a particular type.

```python
from openfga_sdk import OpenFgaClient
from openfga_sdk.models.fga_object import FgaObject
from openfga_sdk.client.models import ClientListUsersRequest, ClientTuple

configuration = ClientConfiguration(
Expand All @@ -697,7 +698,7 @@ async with OpenFgaClient(configuration) as api_client:
}

request = ClientListUsersRequest(
object="document:2021-budget",
object=FgaObject(type="document", id="2021-budget"),
relation="can_read",
user_filters=[
UserTypeFilter(type="user"),
Expand Down
25 changes: 9 additions & 16 deletions config/clients/python/template/client/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ from {{packageName}}.client.models.list_users_request import ClientListUsersRequ
from {{packageName}}.client.models.write_single_response import construct_write_single_response
from {{packageName}}.client.models.write_transaction_opts import WriteTransactionOpts
from {{packageName}}.client.models.read_changes_request import ClientReadChangesRequest
from {{packageName}}.exceptions import FgaValidationException
from {{packageName}}.exceptions import (
AuthenticationError,
FgaValidationException,
UnauthorizedException,
)
from {{packageName}}.models.assertion import Assertion
from {{packageName}}.models.check_request import CheckRequest
from {{packageName}}.models.contextual_tuple_keys import ContextualTupleKeys
Expand Down Expand Up @@ -165,16 +169,6 @@ class OpenFgaClient:
"""
return self._client_configuration.authorization_model_id

{{#asyncio}}async {{/asyncio}}def _check_valid_api_connection(self, options: dict[str, int | str]):
"""
Checks that a connection with the given configuration can be established
"""
authorization_model_id = self._get_authorization_model_id(options)
if authorization_model_id is not None and authorization_model_id != "":
{{#asyncio}}await {{/asyncio}}self.read_authorization_model(options)
else:
{{#asyncio}}await {{/asyncio}}self.read_latest_authorization_model(options)

#################
# Stores
#################
Expand Down Expand Up @@ -380,6 +374,8 @@ class OpenFgaClient:
delete_batch = batch
{{#asyncio}}await {{/asyncio}}self._write_with_transaction(ClientWriteRequest(writes=write_batch, deletes=delete_batch), options)
return [construct_write_single_response(i, True, None) for i in batch]
except (AuthenticationError, UnauthorizedException) as err:
raise err
except Exception as err:
return [construct_write_single_response(i, False, err) for i in batch]

Expand Down Expand Up @@ -449,8 +445,6 @@ class OpenFgaClient:
return results

options = set_heading_if_not_set(options, CLIENT_BULK_REQUEST_ID_HEADER, str(uuid.uuid4()))
# TODO: this should be run in parallel
{{#asyncio}}await {{/asyncio}}self._check_valid_api_connection(options)

# otherwise, it is not a transaction and it is a batch write requests
writes_response = None
Expand Down Expand Up @@ -533,6 +527,8 @@ class OpenFgaClient:
try:
api_response = {{#asyncio}}await {{/asyncio}}self.check(body, options)
return BatchCheckResponse(allowed=api_response.allowed, request=body, response=api_response, error=None)
except (AuthenticationError, UnauthorizedException) as err:
raise err
except Exception as err:
return BatchCheckResponse(allowed=False, request=body, response=None, error=err)
{{#asyncio}}
Expand All @@ -554,9 +550,6 @@ class OpenFgaClient:
options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "BatchCheck")
options = set_heading_if_not_set(options, CLIENT_BULK_REQUEST_ID_HEADER, str(uuid.uuid4()))

# TODO: this should be run in parallel
{{#asyncio}}await {{/asyncio}}self._check_valid_api_connection(options)

max_parallel_requests = {{ clientMaxMethodParallelRequests }}
if options is not None and "max_parallel_requests" in options:
max_parallel_requests = options["max_parallel_requests"]
Expand Down
25 changes: 9 additions & 16 deletions config/clients/python/template/client/client_sync.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ from {{packageName}}.client.models.list_users_request import ClientListUsersRequ
from {{packageName}}.client.models.write_single_response import construct_write_single_response
from {{packageName}}.client.models.write_transaction_opts import WriteTransactionOpts
from {{packageName}}.client.models.read_changes_request import ClientReadChangesRequest
from {{packageName}}.exceptions import FgaValidationException
from {{packageName}}.exceptions import (
AuthenticationError,
FgaValidationException,
UnauthorizedException,
)
from {{packageName}}.models.assertion import Assertion
from {{packageName}}.models.check_request import CheckRequest
from {{packageName}}.models.contextual_tuple_keys import ContextualTupleKeys
Expand Down Expand Up @@ -151,16 +155,6 @@ class OpenFgaClient:
"""
return self._client_configuration.authorization_model_id

def _check_valid_api_connection(self, options: dict[str, int | str]):
"""
Checks that a connection with the given configuration can be established
"""
authorization_model_id = self._get_authorization_model_id(options)
if authorization_model_id is not None and authorization_model_id != "":
self.read_authorization_model(options)
else:
self.read_latest_authorization_model(options)

#################
# Stores
#################
Expand Down Expand Up @@ -366,6 +360,8 @@ class OpenFgaClient:
delete_batch = batch
self._write_with_transaction(ClientWriteRequest(writes=write_batch, deletes=delete_batch), options)
return [construct_write_single_response(i, True, None) for i in batch]
except (AuthenticationError, UnauthorizedException) as err:
raise err
except Exception as err:
return [construct_write_single_response(i, False, err) for i in batch]

Expand Down Expand Up @@ -429,8 +425,6 @@ class OpenFgaClient:
return results

options = set_heading_if_not_set(options, CLIENT_BULK_REQUEST_ID_HEADER, str(uuid.uuid4()))
# TODO: this should be run in parallel
self._check_valid_api_connection(options)

# otherwise, it is not a transaction and it is a batch write requests
writes_response = None
Expand Down Expand Up @@ -512,6 +506,8 @@ class OpenFgaClient:
try:
api_response = self.check(body, options)
return BatchCheckResponse(allowed=api_response.allowed, request=body, response=api_response, error=None)
except (AuthenticationError, UnauthorizedException) as err:
raise err
except Exception as err:
return BatchCheckResponse(allowed=False, request=body, response=None, error=err)

Expand All @@ -529,9 +525,6 @@ class OpenFgaClient:
options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "BatchCheck")
options = set_heading_if_not_set(options, CLIENT_BULK_REQUEST_ID_HEADER, str(uuid.uuid4()))

# TODO: this should be run in parallel
self._check_valid_api_connection(options)

max_parallel_requests = {{ clientMaxMethodParallelRequests }}
if options is not None and "max_parallel_requests" in options:
max_parallel_requests = options["max_parallel_requests"]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{{>partial_header}}

from {{packageName}}.client.models.tuple import ClientTuple
from {{packageName}}.models.fga_object import FgaObject
from {{packageName}}.models.user_type_filter import UserTypeFilter


Expand All @@ -11,7 +12,7 @@ class ClientListUsersRequest:

def __init__(
self,
object: str = None,
object: FgaObject = None,
relation: str = None,
user_filters: list[UserTypeFilter] = None,
contextual_tuples: list[ClientTuple] = None,
Expand All @@ -24,7 +25,7 @@ class ClientListUsersRequest:
self._context = context

@property
def object(self):
def object(self) -> FgaObject:
"""Gets the object of this ClientListUsersRequest.


Expand All @@ -34,7 +35,7 @@ class ClientListUsersRequest:
return self._object

@object.setter
def object(self, object):
def object(self, object: FgaObject):
"""Sets the object of this ClientListUsersRequest.


Expand All @@ -45,7 +46,7 @@ class ClientListUsersRequest:
self._object = object

@property
def relation(self):
def relation(self) -> str:
"""Gets the relation of this ClientListUsersRequest.


Expand All @@ -55,7 +56,7 @@ class ClientListUsersRequest:
return self._relation

@relation.setter
def relation(self, relation):
def relation(self, relation: str):
"""Sets the relation of this ClientListUsersRequest.


Expand All @@ -66,7 +67,7 @@ class ClientListUsersRequest:
self._relation = relation

@property
def user_filters(self):
def user_filters(self) -> list[UserTypeFilter]:
"""Gets the user_filters of this ClientListUsersRequest.


Expand All @@ -76,7 +77,7 @@ class ClientListUsersRequest:
return self._user_filters

@user_filters.setter
def user_filters(self, user_filters):
def user_filters(self, user_filters: list[UserTypeFilter]):
"""Sets the user_filters of this ClientListUsersRequest.


Expand All @@ -87,7 +88,7 @@ class ClientListUsersRequest:
self._user_filters = user_filters

@property
def contextual_tuples(self):
def contextual_tuples(self) -> list[ClientTuple]:
"""Gets the contextual_tuples of this ClientListUsersRequest.


Expand All @@ -97,7 +98,7 @@ class ClientListUsersRequest:
return self._contextual_tuples

@contextual_tuples.setter
def contextual_tuples(self, contextual_tuples):
def contextual_tuples(self, contextual_tuples: list[ClientTuple]):
"""Sets the contextual_tuples of this ClientListUsersRequest.


Expand All @@ -108,7 +109,7 @@ class ClientListUsersRequest:
self._contextual_tuples = contextual_tuples

@property
def context(self):
def context(self) -> object:
"""Gets the context of this ClientListUsersRequest.

Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation.
Expand All @@ -119,7 +120,7 @@ class ClientListUsersRequest:
return self._context

@context.setter
def context(self, context):
def context(self, context: object):
"""Sets the context of this ClientListUsersRequest.

Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation.
Expand Down
8 changes: 7 additions & 1 deletion config/clients/python/template/client/models/tuple.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ class ClientTuple:
ClientTuple encapsulates the client tuple
"""

def __init__(self, user: str, relation: str, object: str, condition: RelationshipCondition = None):
def __init__(
self,
user: str,
relation: str,
object: str,
condition: RelationshipCondition | None = None,
):
self._user = user
self._relation = relation
self._object = object
Expand Down
Loading

0 comments on commit fd85d01

Please sign in to comment.