File size: 8,618 Bytes
cf28a97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import gradio as gr

from huggingface_hub import list_spaces, whoami, HfFolder
from huggingface_hub.hf_api import HfHubHTTPError

def list_my_hf_spaces(hf_username_or_org: str):
    """
    Lists all Hugging Face Spaces for a given username or organization.

    Args:
        hf_username_or_org (str): The Hugging Face username or organization name.

    Returns:
        list: A list of dictionaries, where each dictionary contains details of a space.
              Suitable for use with gradio.DataFrame. Returns a list with an error
              message if an issue occurs.
    """
    try:
        print(f"Fetching Hugging Face Spaces for user/org: {hf_username_or_org}") # Server-side log
        if not hf_username_or_org or not hf_username_or_org.strip():
            # Return list of lists format for error
            return [["Error", "Username/Organization cannot be empty.", "-", "-", "-", "-"]]

        spaces_objects = list_spaces(author=hf_username_or_org.strip())
        
        if not spaces_objects:
            # Return list of lists format for no spaces found
            return [[f"No spaces found for '{hf_username_or_org}'", "Check username/org or authentication.", "-", "-", "-", "-"]]

        spaces_data_list_of_lists = []
        for space in spaces_objects:
            row = [
                f"[{space.id}](https://huggingface.co/spaces/{space.id})",
                getattr(space, 'author', 'N/A'),
                str(getattr(space, 'lastModified', 'N/A')),
                str(getattr(space, 'private', 'N/A')),
                str(getattr(space, 'gated', 'N/A')),
                getattr(space, 'sdk', 'N/A')
            ]
            spaces_data_list_of_lists.append(row)
        
        return spaces_data_list_of_lists

    except Exception as e:
        error_message = f"An error occurred: {str(e)}. Ensure correct username/org and HF authentication (huggingface-cli login or HF_TOKEN)."
        print(error_message) # Server-side log
        # Return list of lists format for exception
        return [["Error", error_message, "-", "-", "-", "-"]]


def list_my_hf_organizations(token: str = None):
    """
    Lists organizations the Hugging Face user (identified by the token) is a member of.

    Args:
        token (str, optional): Hugging Face API token. 
                               If None or empty, attempts to load token via HfFolder.get_token().

    Returns:
        list: A list of lists, where each inner list contains an organization name (as a Markdown link).
              Suitable for use with gradio.DataFrame.
    """
    try:
        if not token: # If token param is None or empty
            token = HfFolder.get_token()
        if not token:
            return [["Error: Not logged in", "Please log in using 'huggingface-cli login'."]]
        
        print("Fetching organizations for the authenticated user...") # Server-side log
        user_info = whoami(token=token)
        
        if not user_info or 'orgs' not in user_info:
            return [["Info", "No organization information found or user data incomplete."]]

        org_list_from_api = user_info.get('orgs', [])
        if not org_list_from_api:
            return [["Info", "Authenticated user is not a member of any organizations."]]

        orgs_data = []
        for org_dict in org_list_from_api:
            org_name = org_dict.get('name')
            if org_name:
                org_link = f"[{org_name}](https://huggingface.co/{org_name})"
                orgs_data.append([org_link]) # Store as a list containing the Markdown link
        
        if not orgs_data:
             return [["Info", "Found organization entries but no names extracted."]]
        return orgs_data

    except HfHubHTTPError as e:
        if e.response.status_code == 401:
            error_msg = "Authentication error. Please ensure you are logged in ('huggingface-cli login')."
        else:
            error_msg = f"API Error: {str(e)}"
        print(error_msg) # Server-side log
        return [["Error", error_msg]]
    except Exception as e:
        error_message = f"An unexpected error occurred: {str(e)}"
        print(error_message) # Server-side log
        return [["Error", error_message]]


def list_organization_spaces(org_name: str):
    """
    Lists all public Hugging Face Spaces for a given organization.

    Args:
        org_name (str): The name of the Hugging Face organization.

    Returns:
        list: A list of lists, where each inner list contains Space details.
              Suitable for use with gradio.DataFrame.
              The Space ID is formatted as a Markdown link.
    """
    try:
        if not org_name or not org_name.strip():
            return [["Error", "Organization name cannot be empty.", "-", "-", "-", "-"]]
        
        print(f"Fetching Hugging Face Spaces for organization: {org_name.strip()}") # Server-side log
        spaces_objects = list_spaces(author=org_name.strip()) # Use author field for organization
        
        if not spaces_objects:
            return [[f"No Spaces found for organization '{org_name.strip()}'", "Organization may not exist or have no public spaces.", "-", "-", "-", "-"]]

        spaces_data_list_of_lists = []
        for space in spaces_objects:
            row = [
                f"[{space.id}](https://huggingface.co/spaces/{space.id})",
                getattr(space, 'author', 'N/A'),
                str(getattr(space, 'lastModified', 'N/A')),
                str(getattr(space, 'private', 'N/A')),
                str(getattr(space, 'gated', 'N/A')),
                getattr(space, 'sdk', 'N/A')
            ]
            spaces_data_list_of_lists.append(row)
        
        return spaces_data_list_of_lists

    except HfHubHTTPError as e:
        error_msg = f"API Error for organization '{org_name.strip()}': {str(e)}"
        print(error_msg) # Server-side log
        return [["Error", error_msg, "-", "-", "-", "-"]]
    except Exception as e:
        error_message = f"An unexpected error occurred for organization '{org_name.strip()}': {str(e)}"
        print(error_message) # Server-side log
        return [["Error", error_message, "-", "-", "-", "-"]]


# Gradio interface for listing Hugging Face Spaces
hf_spaces_interface = gr.Interface(
    fn=list_my_hf_spaces,
    inputs=[gr.Textbox(label="Hugging Face Username or Organization", placeholder="e.g., huggingface, stabilityai, or your_username")],
    outputs=[gr.DataFrame(
        headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"], 
        label="Hugging Face Spaces",
        wrap=True, # Allow text wrapping in cells
        datatype=["markdown", "str", "str", "str", "str", "str"] # Render first column as Markdown
    )],
    title="Hugging Face api as mcp",
    description="Enter a Hugging Face username or organization to list their public Spaces.",
    examples=[["huggingface"], ["stabilityai"], ["gradio"]],
    allow_flagging='never'
)

hf_orgs_interface = gr.Interface(
    fn=list_my_hf_organizations,
    inputs=[gr.Textbox(label="Hugging Face Token (Optional)", placeholder="hf_xxx... or leave blank to use logged-in user", type="password")],
    outputs=[gr.DataFrame(
        headers=["My Organization Name"], 
        label="My Hugging Face Organizations",
        wrap=True,
        datatype=["markdown"] # Render column as Markdown
    )],
    title="My Hugging Face Organizations Lister",
    description="Lists the Hugging Face organizations you are a member of. Requires you to be logged in via 'huggingface-cli login'. Get your token from [here](https://huggingface.co/settings/tokens). Click 'Submit' to refresh.",
    allow_flagging='never'
)


hf_org_spaces_interface = gr.Interface(
    fn=list_organization_spaces,
    inputs=[gr.Textbox(label="Organization Name", placeholder="e.g., huggingface, stabilityai")],
    outputs=[gr.DataFrame(
        headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"], 
        label="Organization's Hugging Face Spaces",
        wrap=True,
        datatype=["markdown", "str", "str", "str", "str", "str"]
    )],
    title="List Organization's Spaces",
    description="Enter a public Hugging Face organization name to list their Spaces.",
    examples=[["huggingface"], ["stabilityai"], ["google"]],
    allow_flagging='never'
)

if __name__ == "__main__":
    tabbed_demo = gr.TabbedInterface(
        [hf_spaces_interface, hf_orgs_interface, hf_org_spaces_interface],
        ["List Spaces by User/Org", "List My Organizations", "List Org Spaces"]
    )
    tabbed_demo.launch(mcp_server=True, share=True)