User and Group Management#
This vignette provides a comprehensive guide to managing users and groups in a Teamworks AMS instance using teamworksams, covering get_user(), get_group(), edit_user(), and create_user(). It equips you to fetch user and group data, update user accounts, and create new users withpractical workflows, detailed examples, best practices, and troubleshooting tips. See Functions and Classes for detailed function documentation and Exporting Data and Importing Data for additional data-related workflows.
Overview#
teamworksams simplifies user and group management through the Teamworks AMS API, offering functions to:
Fetch Users: Retrieve user data (e.g., IDs, names, account info, groups), optionally filtered by attributes like group or email with get_user().
Fetch Groups: List groups accessible to the user with get_group().
Update Users: Modify user fields (e.g., email, name) for existing accounts with edit_user().
Create Users: Add new user accounts with required and optional attributes with create_user()
All examples use the placeholder AMS instance URL
https://example.smartabase.com/site
, username username
, and password
password
, with credentials managed via a .env
file for security and ease of use.
Prerequisites#
Ensure teamworksams is installed and credentials are configured, as described in
Getting Started with teamworksams. The recommended setup is a .env
file:
AMS_URL = https://example.smartabase.com/site
AMS_USERNAME = username
AMS_PASSWORD = password
Load credentials with python-dotenv
:
from dotenv import load_dotenv
load_dotenv()
Alternatively, use os
, direct arguments, or keyring
(see
Managing Credentials, Authentication, and Caching). Required dependencies (installed with
teamworksams): pandas
, requests
, python-dotenv
, tqdm
.
Fetching User Data with get_user()#
The get_user() function retrieves user data as a pandas.DataFrame
, with
optional filtering using a UserFilter
object to narrow results by attributes
like username, email, group, or about field. It’s ideal for auditing user accounts,
generating reports, or identifying specific users.
Basic Usage
Fetch all accessible users:
from teamworksams import get_user, UserOption
df = get_user(
url = "https://example.smartabase.com/site",
option = UserOption(
columns = ["user_id", "first_name", "last_name", "email", "groups"],
interactive_mode = True
)
)
print(df)
Output:
ℹ Fetching user data...
✔ Retrieved 5 users.
user_id first_name last_name email groups
0 12345 John Doe john.doe@example.com [TeamA]
1 12346 Jane Smith jane.smith@example.com [TeamB]
...
Filtering Users
Use UserFilter
to retrieve users in a specific group:
from teamworksams import UserFilter
df = get_user(
url = "https://example.smartabase.com/site",
filter = UserFilter(user_key = "group", user_value = "TeamA"),
option = UserOption(interactive_mode = True)
)
print(df[['user_id', 'first_name', 'groups']])
Output:
ℹ Fetching user data...
✔ Retrieved 2 users.
user_id first_name groups
0 12345 John [TeamA]
1 12347 Bob [TeamA]
Customizing Output
Select specific columns:
df = get_user(
url = "https://example.smartabase.com/site",
option = UserOption(columns = ["user_id", "email"], interactive_mode = True)
)
print(df)
Fetch users by email:
df = get_user(
url = "https://example.smartabase.com/site",
filter = UserFilter(user_key = "email", user_value = ["john.doe@example.com"])
)
print(df[['user_id', 'email']])
Best Practices
Use
UserFilter
to target specific users for efficiency.Limit columns with
option.columns
to optimize DataFrame size.Enable
interactive_mode
for real-time feedback during long operations.
Fetching Group Data with get_group()#
The get_group() function retrieves a list of groups (e.g., teams, departments) as
a pandas.DataFrame
. It’s useful for auditing group structures or preparing data
for user assignments.
Basic Usage
Fetch all accessible groups:
from teamworksams import get_group, GroupOption
group_df = get_group(
url = "https://example.smartabase.com/site",
option = GroupOption(interactive_mode = True)
)
print(group_df)
Output:
ℹ Fetching group data...
✔ Retrieved 3 groups.
name
0 TeamA
1 TeamB
2 TeamC
Best Practices
Use
guess_col_type=True
in GroupOption() to ensure consistent data types.Cache the client for efficiency when combining with get_user().
Updating User Profiles with edit_user()#
The edit_user() function updates existing user fields (e.g., email, name) based on
a mapping DataFrame, using a user key (e.g., username, email) to identify users. It
returns a pandas.DataFrame
of results, making it easy to track updates and
issues. This is a powerful function as it will only update the fields based on columns
provided in the mapping_df
- meaning that it’s possible to just update things like
username, email, e.g. alone.
Basic Usage
Update user emails:
import pandas as pd
from teamworksams import edit_user, UserOption
mapping_df = pd.DataFrame({
"username": ["john.doe", "jane.smith"],
"email": ["john.doe@new.com", "jane.smith@new.com"]
})
results_df = edit_user(
mapping_df = mapping_df,
user_key = "username",
url = "https://example.smartabase.com/site",
option = UserOption(interactive_mode = True)
)
print(results_df)
Output:
ℹ Fetching all user data...
✔ Retrieved 30 users.
ℹ Attempting to map 2 users using username from provided dataframe...
ℹ Successfully mapped 2 users.
ℹ Updating 2 users...
Processing users: 100%|██████████| 2/2 [00:04<00:00, 3.46it/s]
✔ Successfully updated 2 users.
Empty DataFrame
Columns: [user_id, user_key, status, reason]
Index: []
Updating Multiple Fields
Update names and emails using about
as the key:
mapping_df = pd.DataFrame({
"about": ["John Doe", "Jane Smith"],
"first_name": ["Jonathan", "Janet"],
"email": ["jonathan.doe@new.com", "janet.smith@new.com"]
})
results_df = edit_user(
mapping_df = mapping_df,
user_key = "about",
url = "https://example.smartabase.com/site"
)
print(results_df)
Best Practices
Validate
mapping_df
columns against supported fields (e.g.,first_name
,email
,dob
).Use
interactive_mode
for progress tracking and confirmation prompts.Check
results_df
for successful updates and errors.
Creating New Users with create_user()#
The create_user() function adds new user accounts, requiring fields like
first_name
, username
, and password
. It returns a pandas.DataFrame
of failed creations.
Basic Usage
Create a new user:
user_df = pd.DataFrame({
"first_name": ["Alice"],
"last_name": ["Yu"],
"username": ["alice.yu"],
"email": ["alice.yu@example.com"],
"dob": ["1990-01-01"],
"password": ["secure789"],
"active": [True]
})
failed_df = create_user(
user_df = user_df,
url = "https://example.smartabase.com/site",
option = UserOption(interactive_mode = True)
)
print(failed_df)
Output:
ℹ Creating 1 users...
✔ Successfully created 1 users.
Empty DataFrame
Columns: [user_key, reason]
Index: []
Creating Multiple Users
Create users with optional fields:
user_df = pd.DataFrame({
"first_name": ["Bob", "Carol"],
"last_name": ["Lee", "Wong"],
"username": ["bob.lee", "carol.wong"],
"email": ["bob.lee@example.com", "carol.wong@example.com"],
"dob": ["1985-06-15", "1992-03-22"],
"password": ["pass123", "pass456"],
"active": [True, False],
"sex": ["Male", "Female"],
"uuid": ["025380", "024854"]
})
failed_df = create_user(user_df = user_df, url = "https://example.smartabase.com/site")
print(failed_df)
Best Practices
Ensure required fields (
first_name
,last_name
,username
,email
,dob
,password
,active
) are present inuser_df
.Use strong passwords compliant with AMS policies.
Verify
failed_df
for creation issues.
Options and Usage Notes#
This section provides detailed guidance on using option classes (UserOption(), GroupOption(), and the filter class UserFilter() to customize user and group operations, along with key usage notes for caching, column selection, data validation, and interactive mode.
Option Classes
Each user and group function supports a specific option class to configure its behavior.
These classes must be instantiated with parameters like interactive_mode
,
cache
, and others. For example, to select specific columns in get_user():
from teamworksams import get_user, UserOption
df = get_user(
url = "https://example.smartabase.com/site",
option = UserOption(columns = ["user_id", "email"])
)
The option classes and their associated functions are:
Available parameters for UserFilter():
columns (Optional[List[str]]): Only for get_user(). List of column names to include in the output DataFrame (e.g., [‘user_id’, ‘first_name’, ‘email’]). If None, includes all available columns (e.g., ‘user_id’, ‘first_name’, ‘last_name’, ‘email’, ‘groups’, ‘about’, ‘active’, ‘dob’, ‘sex’, ‘uuid’). Defaults to None. Example:
option = UserOption(columns = ["user_id", "email", "groups"]) df = get_user(url = "...", option = option)
interactive_mode (bool): If True, displays status messages (e.g., “Retrieved 5 users” for get_user(), “Successfully updated 2 users” for edit_user()) and
tqdm
progress bars for edit_user() and create_user(). Set to False for silent execution in automated scripts. Defaults to True. Example:option = UserOption(interactive_mode = False) failed_df = create_user(..., option = option) # No output
cache (bool): If True, reuses an existing AMSClient() via get_client(), reducing API calls for authentication or data retrieval. Set to False for fresh data, increasing API overhead. Defaults to True. See “Caching” below.
Available parameters for GroupOption():
guess_col_type (bool): If True, infers column data types in the output DataFrame (e.g., string for ‘name’), ensuring compatibility with operations like merging with get_user() results. Set to False to use default pandas types (e.g., object). Defaults to True. Example:
option = GroupOption(guess_col_type = False) group_df = get_group(url = "...", option = option) print(group_df.dtypes) # name: object
interactive_mode (bool): If True, displays status messages (e.g., “Retrieved 3 groups”). Set to False for silent execution. Defaults to True.
cache (bool): If True, reuses an existing
AMSClient
, reducing API calls. Defaults to True.
Filter Class
The UserFilter() class filters users in get_user() by attributes. For example, to filter by email:
from teamworksams import UserFilter
df = get_user(
url = "https://example.smartabase.com/site",
filter = UserFilter(user_key = "email", user_value = "john.doe@example.com")
)
Available parameters for UserFilter
:
user_key (Optional[str]): Attribute to filter by. Must be one of ‘username’, ‘email’, ‘group’, or ‘about’. For example, ‘group’ filters by group membership (e.g., ‘TeamA’). If None, no filtering is applied. Defaults to None.
user_value (Optional[Union[str, List[str]]]): Value(s) to match for
user_key
. For example, ‘TeamA’ or [‘TeamA’, ‘TeamB’] foruser_key="group"
. Case-sensitive. If None, no filtering is applied. Defaults to None. Example:filter = UserFilter(user_key = "username", user_value = ["john.doe", "jane.smith"]) df = get_user(url = "...", filter = filter)
Valid user_key
values and their user_value
requirements:
username: AMS usernames (e.g., [“john.doe”]).
email: User emails (e.g., [”john.doe@example.com”]).
about: Full names (e.g., [“John Doe”]).
group: Group name (e.g., “TeamA”). Use get_group() to list groups.
Caching
When option.cache=True
(default), functions reuse an existing AMSClient()
created by get_client(), maintaining an authenticated session and reducing API
calls for login or data retrieval. For example:
option = UserOption(cache = True)
user_df = get_user(url = "...", option = option)
group_df = get_group(url = "...", option = GroupOption(cache = True)) # Reuses client
Set cache=False
for independent sessions, ensuring fresh data but increasing API
overhead.
Column Selection
For get_user(), the columns
parameter in UserOption() allows selecting
specific columns from the API response. Supported columns include:
user_id
: Unique AMS-generated user ID.first_name
,last_name
: User’s name.email
: User’s email address.groups
: List of group memberships (e.g., [‘TeamA’]).about
: Full name (concatenation of first and last names).active
: Boolean indicating account status.dob
: Date of birth (format: YYYY-MM-DD or DD/MM/YYYY).sex
: Gender (e.g., “Male”, “Female”).uuid
: Optional unique identifier.Others: Additional fields like
known_as
,language
,sidebar_width
(if available).
Example:
option = UserOption(columns = ["user_id", "email", "active"])
df = get_user(url = "...", option = option)
print(df.dtypes) # user_id: int64, email: object, active: bool
Data Validation
For edit_user(), the mapping_df
DataFrame must include a user_key
column
(one of ‘username’, ‘email’, ‘about’, ‘uuid’) and updatable columns from the supported
list (e.g., first_name
, email
, dob
, sex
, active
, uuid
). Empty values are
sent as empty strings. Example:
mapping_df = pd.DataFrame({
"uuid": ["025380"],
"email": ["new.email@example.com"],
"active": [False]
})
results_df = edit_user(mapping_df = mapping_df, user_key = "uuid", url = "...")
For create_user(), the user_df
DataFrame must include required columns:
first_name
, last_name
, username
, email
, dob
(format: YYYY-MM-DD or DD/MM/YYYY),
password
, active
(boolean). Optional columns include uuid
, known_as
, sex
,
middle_names
, language
, sidebar_width
. Example:
user_df = pd.DataFrame({
"first_name": ["Alice"],
"last_name": ["Yu"],
"username": ["alice.yu"],
"email": ["alice.yu@example.com"],
"dob": ["1990-01-01"],
"password": ["secure789"],
"active": [True],
"sex": ["Female"]
})
failed_df = create_user(user_df = user_df, url = "...")
Validate data before submission to avoid AMSError
:
required = ["first_name", "last_name", "username", "email", "dob", "password", "active"]
if not all(col in user_df.columns for col in required):
print("Missing required columns:", set(required) - set(user_df.columns))
else:
failed_df = create_user(user_df = user_df, url = "...")
Interactive Mode
When interactive_mode=True
(default), functions display progress messages (e.g.,
“ℹ Creating 1 users”) and tqdm
progress bars for edit_user() and
create_user(), enhancing feedback in interactive environments. For
edit_user(), it includes detailed success/failure summaries. Set
interactive_mode=False
for silent execution in automated pipelines:
option = UserOption(interactive_mode = False)
results_df = edit_user(..., option = option) # No output
Error Handling#
teamworksams functions provide descriptive error messages via AMSError
,
with interactive feedback when interactive_mode
is enabled. For simple scripts or
interactive use (e.g., Jupyter notebooks), rely on these messages:
df = get_user(
url = "https://example.smartabase.com/invalid",
option = UserOption(interactive_mode = True)
)
Output:
✖ Failed to log username into https://example.smartabase.com/invalid: Invalid URL or login credentials...
AMSError: Invalid URL or login credentials...
Best Practices#
Security: Store credentials in
.env
orkeyring
to prevent exposure. Keep.env
files in secure, private directories.Data Validation: Verify DataFrame inputs before calling edit_user() or create_user():
if mapping_df.empty: print("Error: Mapping DataFrame is empty") else: failed_df = edit_user(mapping_df, user_key = "username", url = "https://example.smartabase.com/site")
Interactive Mode: Enable for user-friendly feedback during operations.
Caching: Use a cached client for multi-call efficiency:
from teamworksams import get_client client = get_client(url = "https://example.smartabase.com/site", cache = True)
Troubleshooting#
No Users Found:
AMSError: No users returned from server...
Solution: Check credentials and filter settings. Test without filters:
df = get_user(url = "https://example.smartabase.com/site")
Invalid DataFrame:
ValueError: mapping_df is empty...
Solution: Ensure DataFrame is non-empty and includes required columns:
print(mapping_df.columns) # Verify columns failed_df = edit_user(mapping_df, user_key = "username", url = "https://example.smartabase.com/site")
API Errors:
AMSError: Failed to fetch data... (status 503)...
Solution: Check AMS server status. Retry with delay:
from time import sleep for i in range(3): try: df = get_group(url = "https://example.smartabase.com/site") break except AMSError as e: print(f"Retry {i+1}: {e}") sleep(2)
Next Steps#
Explore exporting data in Exporting Data.
Consult Functions and Classes for function details.
Visit GitHub for support.