Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caught blocking call to putrequest with args #666

Closed
devonuto opened this issue Dec 13, 2024 · 5 comments
Closed

Caught blocking call to putrequest with args #666

devonuto opened this issue Dec 13, 2024 · 5 comments

Comments

@devonuto
Copy link

I think maybe this is something to do with it being synchronous? But I'm not sure where to go from here:

Getting this error appear in the logs:

Logger: custom_components.pyscript.file.add_yt_to_sheet.add_to_sheet
Source: custom_components/pyscript/eval.py:510
integration: Pyscript Python scripting ([documentation](https://github.com/custom-components/pyscript), [issues](https://github.com/custom-components/pyscript/issues))
First occurred: 9:01:30 PM (1 occurrences)
Last logged: 9:01:30 PM

Exception in <file.add_yt_to_sheet.add_to_sheet> line 26: spaces='drive' ^ RuntimeError: Caught blocking call to putrequest with args (<httplib2.HTTPSConnectionWithTimeout object at 0x7f5eb7e24c20>, 'POST', '/token') inside the event loop by custom integration 'pyscript' at custom_components/pyscript/eval.py, line 1982: return func(*args, **kwargs). (offender: /usr/local/lib/python3.13/http/client.py, line 1347: self.putrequest(method, url, **skips)), please create a bug report at https://github.com/custom-components/pyscript/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#putrequest

From this Python Script:

import sys
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.discovery import build
from gspread.exceptions import SpreadsheetNotFound
from datetime import datetime
from googleapiclient.errors import HttpError

@service
def add_to_sheet():
    # Use credentials to create a client to interact with the Google Drive API
    scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
    creds = ServiceAccountCredentials.from_json_keyfile_name("/config/homeautomation-google.json", scope)
    client = gspread.authorize(creds)

    # Define the name of the Google Sheet and folder
    sheet_name = "Kids YouTube Videos"
    folder_name = "Home Assistant"

    # Authenticate and build the Drive API client
    drive_service = build('drive', 'v3', credentials=creds)

    # Search for the folder in Google Drive
    response = drive_service.files().list(
        q=f"mimeType='application/vnd.google-apps.folder' and name='{folder_name}' and trashed=false",
        spaces='drive'
    ).execute()

    # Get the folder ID
    folder_id = None
    files = response.get('files', [])
    if files:
        folder_id = files[0].get('id')
        print(f"Folder ID: {folder_id}")

    if not folder_id:
        raise FileNotFoundError(f"Folder '{folder_name}' not found in Google Drive.")

    try:
        # Try to open the Google Sheet
        spreadsheet = client.open(sheet_name)
        sheet = spreadsheet.sheet1
        print(f"Opened existing spreadsheet with title: {spreadsheet.title}")

        # Check if the spreadsheet is already in the correct folder
        file_metadata = drive_service.files().get(fileId=spreadsheet.id, fields='parents').execute()
        parents = file_metadata.get('parents', [])

        if folder_id not in parents:
            # Move the spreadsheet to the folder if it's not already there
            response = drive_service.files().update(
                fileId=spreadsheet.id,
                addParents=folder_id,
                removeParents=','.join(parents),
                fields='id, parents'
            ).execute()
            print("Spreadsheet moved to folder successfully.")
    except SpreadsheetNotFound:
        # If the sheet doesn't exist, create it
        spreadsheet = client.create(sheet_name)
        print(f"Spreadsheet created with ID: {spreadsheet.id}")
        
        try:
            # Move the spreadsheet to the folder
            response = drive_service.files().update(
                fileId=spreadsheet.id,
                addParents=folder_id,
                fields='id, parents'
            ).execute()
            print("Response from moving spreadsheet:", response)
        except HttpError as error:
            print(f"An error occurred while moving the spreadsheet: {error}")
        
        sheet = spreadsheet.sheet1
        # Add headers to the new sheet
        sheet.append_row(["Media Artist", "Media Title", "Media Duration", "Watched At"])

    media_artist = data.get("media_artist")
    media_title = data.get("media_title")
    media_duration = data.get("media_duration")
    watched_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # Append the data to the sheet
    sheet.append_row([media_artist, media_title, media_duration, watched_at])

Does not seem to like the call to Google Drive.

@devonuto
Copy link
Author

devonuto commented Dec 13, 2024

I attempted to resolve using task.executor, but maybe I'm doing it wrong?

import sys
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.discovery import build
from gspread.exceptions import SpreadsheetNotFound
from datetime import datetime
from googleapiclient.errors import HttpError

@service
def add_to_sheet():
    media_artist = data.get("media_artist")
    media_title = data.get("media_title")
    media_duration = data.get("media_duration")
    watched_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # Use @pyscript_executor to run the Google Drive interaction in a separate thread
    @pyscript_executor
    def interact_with_google_drive():
        # Code to interact with Google Drive goes here
        scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
        creds = ServiceAccountCredentials.from_json_keyfile_name(
            "/config/homeautomation-google.json", scope
        )
        client = gspread.authorize(creds)

        # Define the name of the Google Sheet and folder
        sheet_name = "Kids YouTube Videos"
        folder_name = "Home Assistant"

        # Authenticate and build the Drive API client
        drive_service = build('drive', 'v3', credentials=creds)

        # Search for the folder in Google Drive
        response = drive_service.files().list(
            q=f"mimeType='application/vnd.google-apps.folder' and name='{folder_name}' and trashed=false",
            spaces='drive'
        ).execute()

        # Get the folder ID
        folder_id = None
        files = response.get('files', [])
        if files:
            folder_id = files.get('id')
        print(f"Folder ID: {folder_id}")
        if not folder_id:
            raise FileNotFoundError(f"Folder '{folder_name}' not found in Google Drive.")

        try:
            # Try to open the Google Sheet
            spreadsheet = client.open(sheet_name)
            sheet = spreadsheet.sheet1
            print(f"Opened existing spreadsheet with title: {spreadsheet.title}")

            # Check if the spreadsheet is already in the correct folder
            file_metadata = drive_service.files().get(
                fileId=spreadsheet.id, fields='parents'
            ).execute()
            parents = file_metadata.get('parents', [])
            if folder_id not in parents:
                # Move the spreadsheet to the folder if it's not already there
                response = drive_service.files().update(
                    fileId=spreadsheet.id,
                    addParents=folder_id,
                    removeParents=','.join(parents),
                    fields='id, parents'
                ).execute()
                print("Spreadsheet moved to folder successfully.")

        except SpreadsheetNotFound:
            # If the sheet doesn't exist, create it
            spreadsheet = client.create(sheet_name)
            print(f"Spreadsheet created with ID: {spreadsheet.id}")
            try:
                # Move the spreadsheet to the folder
                response = drive_service.files().update(
                    fileId=spreadsheet.id,
                    addParents=folder_id,
                    fields='id, parents'
                ).execute()
                print("Response from moving spreadsheet:", response)
            except HttpError as error:
                print(f"An error occurred while moving the spreadsheet: {error}")
            sheet = spreadsheet.sheet1

            # Add headers to the new sheet
            sheet.append_row(["Media Artist", "Media Title", "Media Duration", "Watched At"])

        # Append the data to the sheet
        sheet.append_row([media_artist, media_title, media_duration, watched_at])

    # Call the function to interact with Google Drive
    interact_with_google_drive()

as I'm still getting errors:

    This error originated from a custom integration.

Logger: custom_components.pyscript.file.add_yt_to_sheet.add_to_sheet
Source: custom_components/pyscript/eval.py:510
integration: Pyscript Python scripting (documentation, issues)
First occurred: 9:01:30 PM (3 occurrences)
Last logged: 9:37:02 PM

Exception in <file.add_yt_to_sheet.add_to_sheet> line 26: spaces='drive' ^ RuntimeError: Caught blocking call to putrequest with args (<httplib2.HTTPSConnectionWithTimeout object at 0x7f5eb7e24c20>, 'POST', '/token') inside the event loop by custom integration 'pyscript' at custom_components/pyscript/eval.py, line 1982: return func(*args, **kwargs). (offender: /usr/local/lib/python3.13/http/client.py, line 1347: self.putrequest(method, url, **skips)), please create a bug report at https://github.com/custom-components/pyscript/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#putrequest
Exception in <file.add_yt_to_sheet.add_to_sheet> line 26: spaces='drive' ^ RuntimeError: Caught blocking call to putrequest with args (<httplib2.HTTPSConnectionWithTimeout object at 0x7f5eaab03390>, 'POST', '/token') inside the event loop by custom integration 'pyscript' at custom_components/pyscript/eval.py, line 1982: return func(*args, **kwargs). (offender: /usr/local/lib/python3.13/http/client.py, line 1347: self.putrequest(method, url, **skips)), please create a bug report at https://github.com/custom-components/pyscript/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#putrequest
Exception in <file.add_yt_to_sheet.add_to_sheet> line 26: spaces='drive' ^ RuntimeError: Caught blocking call to putrequest with args (<httplib2.HTTPSConnectionWithTimeout object at 0x7f5eaf46e210>, 'POST', '/token') inside the event loop by custom integration 'pyscript' at custom_components/pyscript/eval.py, line 1982: return func(*args, **kwargs). (offender: /usr/local/lib/python3.13/http/client.py, line 1347: self.putrequest(method, url, **skips)), please create a bug report at https://github.com/custom-components/pyscript/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#putrequest

@MrBamse
Copy link

MrBamse commented Dec 14, 2024

I just tried importing a native python script for the first time a few minutes ago and calling a function there within and got the same error. I don't know if I'm happy or sad to see that you got the same issue and opened this issue yesterday :)

@jtulak
Copy link

jtulak commented Dec 15, 2024

This is a duplicate of #619. The problem is your code uses (even if indirectly) some blocking call, which is forbidden by Home Assistant.

@devonuto
Copy link
Author

devonuto commented Dec 15, 2024

This is a duplicate of #619. The problem is your code uses (even if indirectly) some blocking call, which is forbidden by Home Assistant.

Sure, I realise that, but that doesn't explain why I'm still getting the same error using @pyscript_executor?

EDIT: Moving the executor definition outside of the system method, that seemed to get rid of that error.

@devonuto
Copy link
Author

Confirmed, after moving @pyscript_executor definition outside of @service definition, the script executes fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants