@@ -54,6 +54,13 @@ class UploadReport:
5454 lines : List [UploadReportLine ]
5555
5656
57+ @dataclass
58+ class Member :
59+ """A member of a user group."""
60+
61+ email : str
62+
63+
5764class UserGroupV2 :
5865 """Upload members to a user group."""
5966
@@ -109,7 +116,7 @@ def upload_members(
109116 "text/csv" ,
110117 )
111118 }
112- query = """mutation ImportMembersToGroup (
119+ query = """mutation ImportMembersToGroupPyPi (
113120 $roleId: ID!
114121 $file: Upload!
115122 $where: WhereUniqueIdInput!
@@ -183,6 +190,46 @@ def upload_members(
183190 csv_report = file_data ["importUsersAsCsvToGroup" ]["csvReport" ]
184191 return self ._parse_csv_report (csv_report )
185192
193+ def export_members (self , group_id : str ) -> Optional [List [Member ]]:
194+ warnings .warn (
195+ "The upload_members for UserGroupV2 is in beta. The method name and signature may change in the future.”" ,
196+ )
197+
198+ if not group_id :
199+ raise ValueError ("Group id is required" )
200+
201+ query = """query GetExportMembersAsCSVPyPi(
202+ $id: ID!
203+ ) {
204+ userGroupV2(where: { id: $id }) {
205+ id
206+ membersAsCSV
207+ }
208+ }
209+ """
210+ params = {
211+ "id" : group_id ,
212+ }
213+
214+ result = self .client .execute (query , params )
215+ if result ["userGroupV2" ] is None :
216+ raise ResourceNotFoundError (message = "The user group is not found." )
217+ data = result ["userGroupV2" ]
218+
219+ # Parse CSV string into list of members
220+ csv_lines = data ["membersAsCSV" ].strip ().split ("\n " )
221+ members_list = []
222+
223+ # Skip header row
224+ for email in csv_lines [1 :]:
225+ members_list .append (
226+ Member (
227+ email = email .strip (),
228+ )
229+ )
230+
231+ return members_list
232+
186233 def _get_role_id (self , role_name : str ) -> Optional [str ]:
187234 role_id = None
188235 query = """query GetAvailableUserRolesPyPi {
0 commit comments