tallyfy 1.0.4__py3-none-any.whl → 1.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tallyfy might be problematic. Click here for more details.

Files changed (34) hide show
  1. tallyfy/__init__.py +8 -4
  2. tallyfy/core.py +11 -8
  3. tallyfy/form_fields_management/__init__.py +70 -0
  4. tallyfy/form_fields_management/base.py +109 -0
  5. tallyfy/form_fields_management/crud_operations.py +234 -0
  6. tallyfy/form_fields_management/options_management.py +222 -0
  7. tallyfy/form_fields_management/suggestions.py +411 -0
  8. tallyfy/models.py +3 -1
  9. tallyfy/task_management/__init__.py +81 -0
  10. tallyfy/task_management/base.py +125 -0
  11. tallyfy/task_management/creation.py +221 -0
  12. tallyfy/task_management/retrieval.py +211 -0
  13. tallyfy/task_management/search.py +196 -0
  14. tallyfy/template_management/__init__.py +85 -0
  15. tallyfy/template_management/analysis.py +1093 -0
  16. tallyfy/template_management/automation.py +469 -0
  17. tallyfy/template_management/base.py +56 -0
  18. tallyfy/template_management/basic_operations.py +477 -0
  19. tallyfy/template_management/health_assessment.py +763 -0
  20. tallyfy/user_management/__init__.py +69 -0
  21. tallyfy/user_management/base.py +146 -0
  22. tallyfy/user_management/invitation.py +286 -0
  23. tallyfy/user_management/retrieval.py +339 -0
  24. {tallyfy-1.0.4.dist-info → tallyfy-1.0.6.dist-info}/METADATA +120 -56
  25. tallyfy-1.0.6.dist-info/RECORD +28 -0
  26. tallyfy/BUILD.md +0 -5
  27. tallyfy/form_fields_management.py +0 -582
  28. tallyfy/task_management.py +0 -356
  29. tallyfy/template_management.py +0 -2607
  30. tallyfy/user_management.py +0 -235
  31. tallyfy-1.0.4.dist-info/RECORD +0 -13
  32. {tallyfy-1.0.4.dist-info → tallyfy-1.0.6.dist-info}/WHEEL +0 -0
  33. {tallyfy-1.0.4.dist-info → tallyfy-1.0.6.dist-info}/licenses/LICENSE +0 -0
  34. {tallyfy-1.0.4.dist-info → tallyfy-1.0.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,339 @@
1
+ """
2
+ User and guest retrieval operations
3
+ """
4
+
5
+ from typing import List, Optional
6
+ from .base import UserManagerBase
7
+ from ..models import User, Guest, TallyfyError
8
+
9
+
10
+ class UserRetrieval(UserManagerBase):
11
+ """Handles user and guest retrieval operations"""
12
+
13
+ def get_current_user_info(self, org_id: str) -> Optional[User]:
14
+ """
15
+ Get current user with full profile data.
16
+
17
+ Args:
18
+ org_id: Organization ID
19
+
20
+ Returns:
21
+ A User object with full profile data
22
+
23
+ Raises:
24
+ TallyfyError: If the request fails
25
+ """
26
+ self._validate_org_id(org_id)
27
+
28
+ try:
29
+ endpoint = f"organizations/{org_id}/me"
30
+ response_data = self.sdk._make_request('GET', endpoint)
31
+
32
+ user_data = self._extract_data(response_data, default_empty=False)
33
+ if user_data:
34
+ # Handle both single user data and wrapped responses
35
+ if isinstance(user_data, list) and user_data:
36
+ return User.from_dict(user_data[0])
37
+ elif isinstance(user_data, dict):
38
+ return User.from_dict(user_data)
39
+
40
+ self.sdk.logger.warning("Unexpected response format for getting current user")
41
+ return None
42
+
43
+ except TallyfyError:
44
+ raise
45
+ except Exception as e:
46
+ self._handle_api_error(e, "get current user info", org_id=org_id)
47
+
48
+ def get_organization_users(self, org_id: str, with_groups: bool = False) -> List[User]:
49
+ """
50
+ Get all organization members with full profile data.
51
+
52
+ Args:
53
+ org_id: Organization ID
54
+ with_groups: Include user groups data
55
+
56
+ Returns:
57
+ List of User objects with full profile data
58
+
59
+ Raises:
60
+ TallyfyError: If the request fails
61
+ """
62
+ self._validate_org_id(org_id)
63
+
64
+ try:
65
+ endpoint = f"organizations/{org_id}/users"
66
+ params = self._build_query_params(**{'with': 'groups'} if with_groups else {})
67
+
68
+ response_data = self.sdk._make_request('GET', endpoint, params=params)
69
+
70
+ users_data = self._extract_data(response_data)
71
+ if users_data:
72
+ return [User.from_dict(user_data) for user_data in users_data]
73
+ else:
74
+ self.sdk.logger.warning("Unexpected response format for users")
75
+ return []
76
+
77
+ except TallyfyError:
78
+ raise
79
+ except Exception as e:
80
+ self._handle_api_error(e, "get organization users", org_id=org_id)
81
+
82
+ def get_organization_users_list(self, org_id: str) -> List[User]:
83
+ """
84
+ Get all organization members with minimal data for listing.
85
+
86
+ Args:
87
+ org_id: Organization ID
88
+
89
+ Returns:
90
+ List of User objects with minimal data
91
+
92
+ Raises:
93
+ TallyfyError: If the request fails
94
+ """
95
+ self._validate_org_id(org_id)
96
+
97
+ try:
98
+ endpoint = f"organizations/{org_id}/users-list"
99
+ response_data = self.sdk._make_request('GET', endpoint)
100
+
101
+ users_data = self._extract_data(response_data)
102
+ if users_data:
103
+ return [User.from_dict(user_data) for user_data in users_data]
104
+ else:
105
+ self.sdk.logger.warning("Unexpected response format for users list")
106
+ return []
107
+
108
+ except TallyfyError:
109
+ raise
110
+ except Exception as e:
111
+ self._handle_api_error(e, "get organization users list", org_id=org_id)
112
+
113
+ def get_organization_guests(self, org_id: str, with_stats: bool = False) -> List[Guest]:
114
+ """
115
+ Get all guests in an organization with full profile data.
116
+
117
+ Args:
118
+ org_id: Organization ID
119
+ with_stats: Include guest statistics
120
+
121
+ Returns:
122
+ List of Guest objects with full profile data
123
+
124
+ Raises:
125
+ TallyfyError: If the request fails
126
+ """
127
+ self._validate_org_id(org_id)
128
+
129
+ try:
130
+ endpoint = f"organizations/{org_id}/guests"
131
+ params = self._build_query_params(**{'with': 'stats'} if with_stats else {})
132
+
133
+ response_data = self.sdk._make_request('GET', endpoint, params=params)
134
+
135
+ guests_data = self._extract_data(response_data)
136
+ if guests_data:
137
+ return [Guest.from_dict(guest_data) for guest_data in guests_data]
138
+ else:
139
+ self.sdk.logger.warning("Unexpected response format for guests")
140
+ return []
141
+
142
+ except TallyfyError:
143
+ raise
144
+ except Exception as e:
145
+ self._handle_api_error(e, "get organization guests", org_id=org_id)
146
+
147
+ def get_organization_guests_list(self, org_id: str) -> List[Guest]:
148
+ """
149
+ Get organization guests with minimal data.
150
+
151
+ Args:
152
+ org_id: Organization ID
153
+
154
+ Returns:
155
+ List of Guest objects with minimal data
156
+
157
+ Raises:
158
+ TallyfyError: If the request fails
159
+ """
160
+ self._validate_org_id(org_id)
161
+
162
+ try:
163
+ endpoint = f"organizations/{org_id}/guests-list"
164
+ response_data = self.sdk._make_request('GET', endpoint)
165
+
166
+ # Handle different response formats
167
+ guests_data = self._extract_data(response_data)
168
+ if guests_data:
169
+ # Handle both list of guests and single guest responses
170
+ if isinstance(guests_data, list):
171
+ return [Guest.from_dict(guest_data) for guest_data in guests_data]
172
+ else:
173
+ return [Guest.from_dict(guests_data)]
174
+ else:
175
+ self.sdk.logger.warning("Unexpected response format for guests list")
176
+ return []
177
+
178
+ except TallyfyError:
179
+ raise
180
+ except Exception as e:
181
+ self._handle_api_error(e, "get organization guests list", org_id=org_id)
182
+
183
+ def get_all_organization_members(self, org_id: str, include_guests: bool = True,
184
+ with_groups: bool = False, with_stats: bool = False) -> dict:
185
+ """
186
+ Get all organization members and optionally guests in a single call.
187
+
188
+ This is a convenience method that combines users and guests data.
189
+
190
+ Args:
191
+ org_id: Organization ID
192
+ include_guests: Whether to include guests in the results
193
+ with_groups: Include user groups data
194
+ with_stats: Include guest statistics
195
+
196
+ Returns:
197
+ Dictionary with 'users' and optionally 'guests' keys
198
+
199
+ Raises:
200
+ TallyfyError: If the request fails
201
+ """
202
+ result = {}
203
+
204
+ # Get users
205
+ result['users'] = self.get_organization_users(org_id, with_groups=with_groups)
206
+
207
+ # Get guests if requested
208
+ if include_guests:
209
+ result['guests'] = self.get_organization_guests(org_id, with_stats=with_stats)
210
+
211
+ return result
212
+
213
+ def get_user_by_email(self, org_id: str, email: str) -> Optional[User]:
214
+ """
215
+ Find a user by email address within an organization.
216
+
217
+ Args:
218
+ org_id: Organization ID
219
+ email: Email address to search for
220
+
221
+ Returns:
222
+ User object if found, None otherwise
223
+
224
+ Raises:
225
+ TallyfyError: If the request fails
226
+ """
227
+ self._validate_org_id(org_id)
228
+ self._validate_email(email)
229
+
230
+ # Get all users and search for the email
231
+ users = self.get_organization_users(org_id)
232
+
233
+ for user in users:
234
+ if hasattr(user, 'email') and user.email and user.email.lower() == email.lower():
235
+ return user
236
+
237
+ return None
238
+
239
+ def get_guest_by_email(self, org_id: str, email: str) -> Optional[Guest]:
240
+ """
241
+ Find a guest by email address within an organization.
242
+
243
+ Args:
244
+ org_id: Organization ID
245
+ email: Email address to search for
246
+
247
+ Returns:
248
+ Guest object if found, None otherwise
249
+
250
+ Raises:
251
+ TallyfyError: If the request fails
252
+ """
253
+ self._validate_org_id(org_id)
254
+ self._validate_email(email)
255
+
256
+ # Get all guests and search for the email
257
+ guests = self.get_organization_guests(org_id)
258
+
259
+ for guest in guests:
260
+ if hasattr(guest, 'email') and guest.email and guest.email.lower() == email.lower():
261
+ return guest
262
+
263
+ return None
264
+
265
+ def search_members_by_name(self, org_id: str, name_query: str, include_guests: bool = True) -> dict:
266
+ """
267
+ Search for organization members by name (first name, last name, or full name).
268
+
269
+ Args:
270
+ org_id: Organization ID
271
+ name_query: Name to search for (case-insensitive partial match)
272
+ include_guests: Whether to include guests in the search
273
+
274
+ Returns:
275
+ Dictionary with 'users' and optionally 'guests' keys containing matching members
276
+
277
+ Raises:
278
+ TallyfyError: If the request fails
279
+ """
280
+ self._validate_org_id(org_id)
281
+
282
+ if not name_query or not isinstance(name_query, str):
283
+ raise ValueError("Name query must be a non-empty string")
284
+
285
+ name_query_lower = name_query.lower()
286
+ result = {'users': [], 'guests': []}
287
+
288
+ # Search users
289
+ users = self.get_organization_users(org_id)
290
+ for user in users:
291
+ user_matches = False
292
+
293
+ # Check first name
294
+ if hasattr(user, 'first_name') and user.first_name:
295
+ if name_query_lower in user.first_name.lower():
296
+ user_matches = True
297
+
298
+ # Check last name
299
+ if hasattr(user, 'last_name') and user.last_name:
300
+ if name_query_lower in user.last_name.lower():
301
+ user_matches = True
302
+
303
+ # Check full name
304
+ if hasattr(user, 'first_name') and hasattr(user, 'last_name'):
305
+ if user.first_name and user.last_name:
306
+ full_name = f"{user.first_name} {user.last_name}".lower()
307
+ if name_query_lower in full_name:
308
+ user_matches = True
309
+
310
+ if user_matches:
311
+ result['users'].append(user)
312
+
313
+ # Search guests if requested
314
+ if include_guests:
315
+ guests = self.get_organization_guests(org_id)
316
+ for guest in guests:
317
+ guest_matches = False
318
+
319
+ # Check first name
320
+ if hasattr(guest, 'first_name') and guest.first_name:
321
+ if name_query_lower in guest.first_name.lower():
322
+ guest_matches = True
323
+
324
+ # Check last name
325
+ if hasattr(guest, 'last_name') and guest.last_name:
326
+ if name_query_lower in guest.last_name.lower():
327
+ guest_matches = True
328
+
329
+ # Check full name
330
+ if hasattr(guest, 'first_name') and hasattr(guest, 'last_name'):
331
+ if guest.first_name and guest.last_name:
332
+ full_name = f"{guest.first_name} {guest.last_name}".lower()
333
+ if name_query_lower in full_name:
334
+ guest_matches = True
335
+
336
+ if guest_matches:
337
+ result['guests'].append(guest)
338
+
339
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tallyfy
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: A comprehensive Python SDK for interacting with the Tallyfy API
5
5
  Home-page: https://github.com/tallyfy/tallyfy-sdk
6
6
  Author: Tallyfy
@@ -31,6 +31,7 @@ Description-Content-Type: text/markdown
31
31
  License-File: LICENSE
32
32
  Requires-Dist: requests>=2.25.0
33
33
  Requires-Dist: typing-extensions>=4.0.0; python_version < "3.8"
34
+ Requires-Dist: email-validator==2.2.0
34
35
  Provides-Extra: dev
35
36
  Requires-Dist: pytest>=6.0.0; extra == "dev"
36
37
  Requires-Dist: pytest-cov>=2.10.0; extra == "dev"
@@ -62,7 +63,7 @@ A comprehensive Python SDK for interacting with the Tallyfy API. This SDK provid
62
63
  ## Installation
63
64
 
64
65
  ```bash
65
- pip install -r requirements.txt
66
+ pip install tallyfy
66
67
  ```
67
68
 
68
69
  **Dependencies:**
@@ -101,12 +102,11 @@ The Tallyfy SDK follows a modular architecture with specialized management class
101
102
  - **`TallyfySDK`** - Main SDK class that orchestrates all operations with backward compatibility methods
102
103
  - **`BaseSDK`** - Base class with HTTP request handling, retry logic, and connection pooling
103
104
  - **Management Modules:**
104
- - `UserManagement` - User and guest operations with full profile support
105
- - `TaskManagement` - Task and process operations with natural language processing
106
- - `TemplateManagement` - Template/checklist operations with automation analysis
107
- - `FormFieldManagement` - Form field operations with AI-powered suggestions
108
- - **Utility Modules:**
109
- - `DateExtractor` - Natural language date parsing and task extraction
105
+ - `UserManager` - User and guest operations with modular retrieval and invitation components
106
+ - `TaskManager` - Task and process operations with search and creation capabilities
107
+ - `TemplateManager` - Template/checklist operations with automation analysis and health assessment
108
+ - `FormFieldManager` - Form field operations with AI-powered suggestions and dropdown management
109
+ - **Error Handling:**
110
110
  - `TallyfyError` - Custom exception handling with status codes and response data
111
111
 
112
112
  ### File Structure
@@ -116,10 +116,30 @@ tallyfy/
116
116
  ├── __init__.py # SDK exports and version
117
117
  ├── core.py # BaseSDK and TallyfySDK classes
118
118
  ├── models.py # Data models and types
119
- ├── user_management.py # User and guest management
120
- ├── task_management.py # Task and process management
121
- ├── template_management.py # Template management
122
- ├── form_fields_management.py # Form field management
119
+ ├── user_management/ # User and guest management (modular)
120
+ ├── __init__.py # UserManager with unified interface
121
+ ├── base.py # Common validation and error handling
122
+ ├── retrieval.py # User and guest retrieval operations
123
+ │ └── invitation.py # User invitation operations
124
+ ├── task_management/ # Task and process management (modular)
125
+ │ ├── __init__.py # TaskManager with unified interface
126
+ │ ├── base.py # Common task operations base
127
+ │ ├── retrieval.py # Task and process retrieval
128
+ │ ├── search.py # Search functionality
129
+ │ └── creation.py # Task creation operations
130
+ ├── template_management/ # Template management (modular)
131
+ │ ├── __init__.py # TemplateManager with unified interface
132
+ │ ├── base.py # Common template operations
133
+ │ ├── basic_operations.py # Template retrieval and CRUD operations
134
+ │ ├── automation.py # Automation rule management
135
+ │ ├── analysis.py # Template analysis and health checks
136
+ │ └── health_assessment.py # Template health assessment functionality
137
+ ├── form_fields_management/ # Form field management (modular)
138
+ │ ├── __init__.py # FormFieldManager with unified interface
139
+ │ ├── base.py # Common form field operations
140
+ │ ├── crud_operations.py # CRUD operations for form fields
141
+ │ ├── options_management.py # Dropdown options management
142
+ │ └── suggestions.py # AI-powered field suggestions
123
143
  └── README.md # This documentation
124
144
  ```
125
145
 
@@ -133,16 +153,19 @@ tallyfy/
133
153
  - Comprehensive error handling with detailed error information
134
154
 
135
155
  ### 👥 User Management
156
+ - **Modular architecture** with specialized retrieval and invitation components
136
157
  - Get organization members with full profile data (country, timezone, job details)
137
158
  - Get minimal user lists for performance-critical operations
138
159
  - Manage guests and external users with guest-specific features
139
- - Invite new users to organization with role assignment
140
- - Support for user groups and permissions
160
+ - **Enhanced search capabilities** - Find users by email or name with fuzzy matching
161
+ - **Batch invitation support** - Invite multiple users with default roles and messages
162
+ - **Advanced invitation features** - Custom messages, role validation, and resend functionality
163
+ - Support for user groups and permissions with flexible query parameters
164
+ - **Convenience methods** - Get all members (users + guests) in a single call
141
165
 
142
166
  ### ✅ Task Management
143
167
  - Get tasks for specific users or processes with filtering
144
168
  - Create standalone tasks with rich assignment options
145
- - **Natural language task creation** with automatic date/time extraction
146
169
  - Search processes by name with fuzzy matching
147
170
  - Advanced filtering for organization runs (status, owners, tags, etc.)
148
171
  - Universal search across processes, templates, and tasks
@@ -175,16 +198,8 @@ tallyfy/
175
198
  - Exact and fuzzy matching with relevance scoring
176
199
  - Pagination support with configurable page sizes
177
200
  - Rich search results with metadata and context
178
- - **Natural language date extraction** from search queries
179
201
  - Process and template name-based search with suggestions
180
202
 
181
- ### 🤖 Natural Language Processing
182
- - **Task creation from natural language** with automatic parsing
183
- - **Date extraction** supporting various formats ("next Monday at 12PM", "tomorrow morning")
184
- - **User/guest resolution** from names and emails
185
- - **Smart task parsing** extracting titles, descriptions, and deadlines
186
- - **Fuzzy matching** for user names and process titles
187
-
188
203
  ## API Reference
189
204
 
190
205
  ### SDK Initialization
@@ -201,20 +216,88 @@ TallyfySDK(
201
216
  ### User Management
202
217
 
203
218
  ```python
204
- # Get all organization users
219
+ # Get all organization users with optional group data
205
220
  users = sdk.users.get_organization_users(org_id, with_groups=False)
206
221
 
207
- # Get minimal user list
222
+ # Get minimal user list for performance
208
223
  users_list = sdk.users.get_organization_users_list(org_id)
209
224
 
210
- # Get organization guests
225
+ # Get organization guests with optional statistics
211
226
  guests = sdk.users.get_organization_guests(org_id, with_stats=False)
212
227
 
213
- # Invite user to organization
228
+ # Get current user info
229
+ current_user = sdk.users.get_current_user_info(org_id)
230
+
231
+ # Enhanced search capabilities
232
+ user = sdk.users.get_user_by_email(org_id, "john@company.com")
233
+ guest = sdk.users.get_guest_by_email(org_id, "contractor@company.com")
234
+
235
+ # Search members by name (fuzzy matching)
236
+ search_results = sdk.users.search_members_by_name(org_id, "John Smith", include_guests=True)
237
+ matching_users = search_results['users']
238
+ matching_guests = search_results['guests']
239
+
240
+ # Get all members in one call
241
+ all_members = sdk.users.get_all_organization_members(
242
+ org_id, include_guests=True, with_groups=True, with_stats=True
243
+ )
244
+
245
+ # Invite single user to organization
214
246
  user = sdk.users.invite_user_to_organization(
215
- org_id, email, first_name, last_name,
216
- role="light", message=None
247
+ org_id, email="new.hire@company.com",
248
+ first_name="John", last_name="Doe",
249
+ role="standard",
250
+ message="Welcome! Please complete your onboarding process."
251
+ )
252
+
253
+ # Batch invite multiple users
254
+ invitations = [
255
+ {
256
+ "email": "user1@company.com",
257
+ "first_name": "Jane",
258
+ "last_name": "Smith",
259
+ "role": "standard"
260
+ },
261
+ {
262
+ "email": "user2@company.com",
263
+ "first_name": "Bob",
264
+ "last_name": "Johnson",
265
+ "message": "Welcome to the engineering team!"
266
+ }
267
+ ]
268
+ results = sdk.users.invite_multiple_users(
269
+ org_id, invitations,
270
+ default_role="light",
271
+ default_message="Welcome to our organization!"
272
+ )
273
+
274
+ # Resend invitation
275
+ success = sdk.users.resend_invitation(
276
+ org_id, email="pending@company.com",
277
+ message="Reminder: Please accept your invitation to join our organization."
217
278
  )
279
+
280
+ # Generate custom invitation message
281
+ message = sdk.users.get_invitation_template_message(
282
+ org_name="ACME Corp",
283
+ custom_text="We're excited to have you join our innovative team!"
284
+ )
285
+
286
+ # Validate invitation data before sending
287
+ invitation_data = {
288
+ "email": "new@company.com",
289
+ "first_name": "Alice",
290
+ "last_name": "Wilson",
291
+ "role": "admin"
292
+ }
293
+ validated_data = sdk.users.validate_invitation_data(invitation_data)
294
+
295
+ # Access modular components directly (advanced usage)
296
+ # Retrieval operations
297
+ users_with_groups = sdk.users.retrieval.get_organization_users(org_id, with_groups=True)
298
+
299
+ # Invitation operations
300
+ batch_results = sdk.users.invitation.invite_multiple_users(org_id, invitations)
218
301
  ```
219
302
 
220
303
  ### Task Management
@@ -244,14 +327,6 @@ task = sdk.tasks.create_task(
244
327
  description="Please review the attached document"
245
328
  )
246
329
 
247
- # Create task from natural language (via MCP Server)
248
- task_result = create_task_from_text(
249
- org_id,
250
- "Create a task called Review Document with description Review the quarterly report the deadline is next Monday at 12PM",
251
- user_emails=["john@company.com"],
252
- max_assignable=2
253
- )
254
-
255
330
  # Search processes, templates, or tasks
256
331
  results = sdk.tasks.search(org_id, "onboarding", search_type="process")
257
332
 
@@ -306,14 +381,13 @@ suggestions = sdk.templates.suggest_automation_consolidation(org_id, template_id
306
381
  # Assess overall template health
307
382
  health_report = sdk.templates.assess_template_health(org_id, template_id)
308
383
 
309
- # Add kickoff fields
310
- kickoff_data = {
311
- "field_type": "text",
312
- "label": "Project Name",
313
- "required": True,
314
- "validation_rules": {"min_length": 3}
315
- }
316
- kickoff_field = sdk.templates.add_kickoff_field(org_id, template_id, kickoff_data)
384
+ # Template metadata management
385
+ updated = sdk.templates.update_template_metadata(
386
+ org_id, template_id,
387
+ title="Updated Template Title",
388
+ guidance="New guidance text",
389
+ is_featured=True
390
+ )
317
391
 
318
392
  # Add assignees to step
319
393
  assignees = {"users": [123, 456], "groups": ["managers"], "guests": ["contractor@company.com"]}
@@ -640,13 +714,6 @@ enhance_template_with_smart_fields(org_id, "your_template_id")
640
714
 
641
715
  ## Contributing
642
716
 
643
- ### Development Setup
644
-
645
- 1. Clone the repository
646
- 2. Install dependencies: `pip install -r requirements.txt`
647
- 3. Set up environment variables in `.env`
648
- 4. Run tests: `python -m pytest tests/`
649
-
650
717
  ### Code Style
651
718
 
652
719
  - Follow PEP 8 style guidelines
@@ -662,9 +729,6 @@ enhance_template_with_smart_fields(org_id, "your_template_id")
662
729
  4. Include error handling and logging
663
730
  5. Update this README with usage examples
664
731
 
665
- ## License
666
-
667
- This SDK is part of the Tallyfy MCP project. See the main project repository for license information.
668
732
 
669
733
  ## Support
670
734
 
@@ -674,5 +738,5 @@ For bugs, feature requests, or questions:
674
738
  2. Contact us at: support@tallyfy.com
675
739
  ---
676
740
 
677
- **Version:** 1.0.4
741
+ **Version:** 1.0.6
678
742
  **Last Updated:** 2025
@@ -0,0 +1,28 @@
1
+ tallyfy/__init__.py,sha256=vE4XedttVizpD6kJHpTkg686xmokJwQ4rZ749yUCKEA,638
2
+ tallyfy/core.py,sha256=ZEQQIIUDajH8t4RVPxtqu9VR2mFurDBH_o5Hzl0YUUA,16590
3
+ tallyfy/models.py,sha256=6TcrkaLtbp7zz1ZCW6W3Gk5k9Jyp305I1QpLRgO1uw8,38136
4
+ tallyfy/form_fields_management/__init__.py,sha256=epEFynMhcKUKJhY58ZtZ_fCkreBMtg9HbbEQouvK8FM,2567
5
+ tallyfy/form_fields_management/base.py,sha256=6YH5wGTlG1EDEuEFxROz4CPadNHOVX1UZY1zLlfTqbg,3215
6
+ tallyfy/form_fields_management/crud_operations.py,sha256=3XCJunGwMo8z4we8fva8zRryKajBcQMt9Jgg_Y_QM5Q,8877
7
+ tallyfy/form_fields_management/options_management.py,sha256=cZWGBkR3770NEDQYDj9I1ug5lhGQ4tH482sZW6qkapk,8640
8
+ tallyfy/form_fields_management/suggestions.py,sha256=4XaYG7SHAXjjxnVLDGtd0FGOxPrBzPnp4fTjd-Iuj34,16866
9
+ tallyfy/task_management/__init__.py,sha256=5pknQarjvQZtv3Sa2GXxlMqSZ9skCIE6DsJwaGBQWU4,2963
10
+ tallyfy/task_management/base.py,sha256=lHYvdFQh0YlFYawDnApZVU37UWnPkePFcYqFK1QLS1c,4027
11
+ tallyfy/task_management/creation.py,sha256=reaiAFWH7GIlNLTzGwqgJX5iXbHUROXh5oFgEXv-bX4,9012
12
+ tallyfy/task_management/retrieval.py,sha256=fWsED0K_DnDunQl-Y2B7uIjtqz47LdP4oLhrXAUNKYA,7926
13
+ tallyfy/task_management/search.py,sha256=2bFMIsnjq-sE8inj0EP_bK_Ituuq-59bcq9cYedDEmw,7404
14
+ tallyfy/template_management/__init__.py,sha256=9ID-EHNIyucko5TBWagVSp3FKi9ADjNfRMWyT7rPSAo,3674
15
+ tallyfy/template_management/analysis.py,sha256=9rCAw5B8k5919_PUCUAaJe-hJ8n1yCB27rSZWCbYGlg,51547
16
+ tallyfy/template_management/automation.py,sha256=jJnVBdLKUkuS7NsxKmQQ-MGoS0vb9xiX-EOqVNoNcQQ,19809
17
+ tallyfy/template_management/base.py,sha256=wP18jd5T06QwCV2rw4FhSDQCEKlAMwbSg5ffd8vSDVw,2031
18
+ tallyfy/template_management/basic_operations.py,sha256=RzZSvGJ8Q0fcF_c6Vk_PrFhp0rGJ_UUMd3YfxgY5AwE,18888
19
+ tallyfy/template_management/health_assessment.py,sha256=ApyLE3j_XnmtmGsRjWvjPp2faQIcmToi9PvZ0hrVk4o,32085
20
+ tallyfy/user_management/__init__.py,sha256=LTyxJ7i4JrsUMf8QMdtrLdwbgtv8_mmMi8eUmo5Yre8,2658
21
+ tallyfy/user_management/base.py,sha256=jD5jOAu3y0K7fumSH65t9zFRDLriOV-YYPZSuJzYuTE,4681
22
+ tallyfy/user_management/invitation.py,sha256=Ss1Gtii-sS02GuY-XUPYi7dHwAKWMkaG_tRFVOfS_2Q,11395
23
+ tallyfy/user_management/retrieval.py,sha256=M5xFlY2IPIR2b5TUbF0YF2Cm12Mdnu5ZU1iahBFI1vA,11696
24
+ tallyfy-1.0.6.dist-info/licenses/LICENSE,sha256=8HUsrXnc3l2sZxhPV9Z1gYinq76Q2Ym7ahYJy57QlLc,1063
25
+ tallyfy-1.0.6.dist-info/METADATA,sha256=ayLEgfiP9ESfd0MH2HAfYGhVgo3guelApM2QabEAQQo,26359
26
+ tallyfy-1.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ tallyfy-1.0.6.dist-info/top_level.txt,sha256=yIycWbR61EZJD0MYRPwUQjOS2XZw5B5jCWx1IP73KcM,8
28
+ tallyfy-1.0.6.dist-info/RECORD,,
tallyfy/BUILD.md DELETED
@@ -1,5 +0,0 @@
1
- ### Build
2
- python3 -m build
3
-
4
- ### Publish
5
- python -m twine upload dist/tallyfy-version*