Skip to content

Commit

Permalink
Merge pull request #2 from umn-microsoft-automation/documentation
Browse files Browse the repository at this point in the history
Documentation
  • Loading branch information
FISHMANPET authored May 10, 2023
2 parents 5ebc3f5 + d01d454 commit 3154b9d
Show file tree
Hide file tree
Showing 30 changed files with 1,343 additions and 292 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,36 @@

This is a module to interact with the [Grouper Web Services API](https://spaces.at.internet2.edu/display/Grouper/Grouper+Web+Services).

## Basic Usage

Operations will start by creating a `GrouperClient` object.

``` python
from grouper_python import GrouperClient

grouper_client = GrouperClient(base_url, username, password)
```

`GrouperClient` can also be used as a context manager.

``` python
from grouper_python import GrouperClient

with GrouperClient(base_url, username, password) as grouper_client:
...
```

The `base_url` should end in something like
`grouper-ws/servicesRest/v2_6_000`.

With a `GrouperClient` object, you can query for a subject, stem, or group.
You can also "search" for groups or subjects.

Once you have an object, you can perform various operations against it.
To create a new group or stem for example, you would get the "parent" stem,
and then use `create_child_stem()` or `create_child_group()` to create that
stem or group in that parent.

## Installation

To install grouper library only:
Expand Down
13 changes: 6 additions & 7 deletions grouper_python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from .objects.client import Client
from .objects.group import Group
from .objects.stem import Stem
from .objects.subject import Subject
from .objects.person import Person
"""grouper_python, a Python package for interacting with Grouper Web Services."""

__version__ = "0.1.0"
from .objects.client import GrouperClient

__all__ = ["Client", "Group", "Stem", "Subject", "Person"]
Client = GrouperClient

__version__ = "0.1.1"
__all__ = ["GrouperClient"]
99 changes: 88 additions & 11 deletions grouper_python/group.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
"""grouper-python.group - functions to interact with group objects.
These are "helper" functions that most likely will not be called directly.
Instead, a GrouperClient class should be created, then from there use that
GrouperClient's methods to find and create objects, and use those objects' methods.
These helper functions are used by those objects, but can be called
directly if needed.
"""

from __future__ import annotations
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING: # pragma: no cover
from .objects.group import CreateGroup, Group
from .objects.client import Client
from .objects.client import GrouperClient
from .objects.subject import Subject
from .objects.exceptions import (
GrouperGroupNotFoundException,
Expand All @@ -15,10 +24,25 @@

def find_group_by_name(
group_name: str,
client: Client,
client: GrouperClient,
stem: str | None = None,
act_as_subject: Subject | None = None,
) -> list[Group]:
"""Find a group or groups by approximate name.
:param group_name: The group name to search for
:type group_name: str
:param client: The GrouperClient to use
:type client: GrouperClient
:param stem: Optional stem to limit the search to, defaults to None
:type stem: str | None, optional
:param act_as_subject: Optional subject to act as, defaults to None
:type act_as_subject: Subject | None, optional
:raises GrouperStemNotFoundException: The specified stem cannot be found
:raises GrouperSuccessException: An otherwise unhandled issue with the result
:return: List of found groups, will be an empty list if no groups are found
:rtype: list[Group]
"""
from .objects.group import Group

body = {
Expand All @@ -45,10 +69,10 @@ def find_group_by_name(
raise GrouperStemNotFoundException(str(stem), r)
else: # pragma: no cover
# Some other issue, so pass the failure through
raise
raise err
if "groupResults" in r["WsFindGroupsResults"]:
return [
Group.from_results(client, grp)
Group(client, grp)
for grp in r["WsFindGroupsResults"]["groupResults"]
]
else:
Expand All @@ -57,9 +81,20 @@ def find_group_by_name(

def create_groups(
groups: list[CreateGroup],
client: Client,
client: GrouperClient,
act_as_subject: Subject | None = None,
) -> list[Group]:
"""Create groups.
:param groups: List of groups to create
:type groups: list[CreateGroup]
:param client: The GrouperClient to use
:type client: GrouperClient
:param act_as_subject: Optional subject to act as, defaults to None
:type act_as_subject: Subject | None, optional
:return: Group objects representing the created groups
:rtype: list[Group]
"""
from .objects.group import Group

groups_to_save = []
Expand Down Expand Up @@ -87,16 +122,29 @@ def create_groups(
act_as_subject=act_as_subject,
)
return [
Group.from_results(client, result["wsGroup"])
Group(client, result["wsGroup"])
for result in r["WsGroupSaveResults"]["results"]
]


def delete_groups(
group_names: list[str],
client: Client,
client: GrouperClient,
act_as_subject: Subject | None = None,
) -> None:
"""Delete the given groups.
:param group_names: The names of groups to delete
:type group_names: list[str]
:param client: The GrouperClient to use
:type client: GrouperClient
:param act_as_subject: Optional subject to act as, defaults to None
:type act_as_subject: Subject | None, optional
:raises GrouperPermissionDenied: Permission denied to complete the operation
:raises GrouperGroupNotFoundException: A group with the given name cannot
be found
:raises GrouperSuccessException: An otherwise unhandled issue with the result
"""
group_lookup = [{"groupName": group} for group in group_names]
body = {
"WsRestGroupDeleteRequest": {
Expand Down Expand Up @@ -139,10 +187,25 @@ def delete_groups(

def get_groups_by_parent(
parent_name: str,
client: Client,
client: GrouperClient,
recursive: bool = False,
act_as_subject: Subject | None = None,
) -> list[Group]:
"""Get Groups within the given parent stem.
:param parent_name: The parent stem to look in
:type parent_name: str
:param client: The GrouperClient to use
:type client: GrouperClient
:param recursive: Whether to look recursively through the entire subtree (True),
or only one level in the given parent (False), defaults to False
:type recursive: bool, optional
:param act_as_subject: Optional subject to act as, defaults to None
:type act_as_subject: Subject | None, optional
:raises GrouperSuccessException: An otherwise unhandled issue with the result
:return: The list of Groups found
:rtype: list[Group]
"""
from .objects.group import Group

body = {
Expand All @@ -162,7 +225,7 @@ def get_groups_by_parent(
)
if "groupResults" in r["WsFindGroupsResults"]:
return [
Group.from_results(client, grp)
Group(client, grp)
for grp in r["WsFindGroupsResults"]["groupResults"]
]
else:
Expand All @@ -171,9 +234,23 @@ def get_groups_by_parent(

def get_group_by_name(
group_name: str,
client: Client,
client: GrouperClient,
act_as_subject: Subject | None = None,
) -> Group:
"""Get a group with the given name.
:param group_name: The name of the group to get
:type group_name: str
:param client: The GrouperClient to use
:type client: GrouperClient
:param act_as_subject: Optional subject to act as, defaults to None
:type act_as_subject: Subject | None, optional
:raises GrouperGroupNotFoundException: A group with the given name cannot
be found
:raises GrouperSuccessException: An otherwise unhandled issue with the result
:return: The group with the given name
:rtype: Group
"""
from .objects.group import Group

body = {
Expand All @@ -186,4 +263,4 @@ def get_group_by_name(
r = client._call_grouper("/groups", body, act_as_subject=act_as_subject)
if "groupResults" not in r["WsFindGroupsResults"]:
raise GrouperGroupNotFoundException(group_name, r)
return Group.from_results(client, r["WsFindGroupsResults"]["groupResults"][0])
return Group(client, r["WsFindGroupsResults"]["groupResults"][0])
Loading

0 comments on commit 3154b9d

Please sign in to comment.