Raise error

While running a plugin there are several situations where problems or network errors can appear. Is there a way to raise on error with significant error message?

 

My thoughts go to a try / catch clause but I cannot figure out how to tell plex that there was a failure and raise an exception.

 

Greets

Sascha

There are a number of exceptions defined in the Framework.

  • MediaNotAvailable
  • MediaExpired
  • LiveMediaNotStarted
  • MediaNotAuthorized
  • MediaGeoblocked
  • StreamLimitExceeded

These can be raised from within a try/except block. Like here in the Vimeo Service. The exception will be logged but, in my experience few clients actually pass the error on to the user. I think PHT is the only client that currently does (perhaps iOS too). If you wish to notify the user, you might consider returning an ObjectContainer from your try/except block with a header & message.

try:
  ''' do stuff '''
  return ObjectContainer(blah) #desired result
except:
  ''' on error '''
  return ObjectContainer(header="Error", message="Failed to load stuff")

After calling the plugin I'm testing the configuration. If there's an error (missing config) I'd like to display an error AND add the preferences object.

If I just return a message, the preferences menu is missing...

After calling the plugin I'm testing the configuration. If there's an error (missing config) I'd like to display an error AND add the preferences object.

If I just return a message, the preferences menu is missing...

Did you try adding the PrefsObject to the ObjectContainer before returning the message?

try:
  ...
except:
  oc = ObjectContainer(header="blah", message="blahblah")
  oc.add(PrefsObject(summary="Add your config details"))
  return oc

Works, the order was the problem...

:D

There are a number of exceptions defined in the Framework.

  • MediaNotAvailable
  • MediaExpired
  • LiveMediaNotStarted
  • MediaNotAuthorized
  • MediaGeoblocked
  • StreamLimitExceeded

These can be raised from within a try/except block. Like here in the Vimeo Service. The exception will be logged but, in my experience few clients actually pass the error on to the user. I think PHT is the only client that currently does (perhaps iOS too). If you wish to notify the user, you might consider returning an ObjectContainer from your try/except block with a header & message.

try:
  ''' do stuff '''
  return ObjectContainer(blah) #desired result
except:
  ''' on error '''
  return ObjectContainer(header="Error", message="Failed to load stuff")

This looks like what I was looking for as well, although I seem to be running into issues getting the exception to catch from within my __init__.py file. As the example is from a Service, Is it safe to assume that these exceptions can only be caught from within a service and not within the __init__.py?

TIA!

This looks like what I was looking for as well, although I seem to be running into issues getting the exception to catch from within my __init__.py file. As the example is from a Service, Is it safe to assume that these exceptions can only be caught from within a service and not within the __init__.py?

TIA!

These exceptions, and try/except blocks in general, should work in the __init__.py file as well as the ServiceCode.pys file. These exceptions are not generated automatically but are options available to channel developers to notify the framework (and in theory users) about an error and the reason for it.

How is it failing for you? Does the try-statement not fallback to your except-statement? Is the exception not being logged?

It may be helpful to include a snippet of the code that isn't working for you, or link to somewhere you have it hosted online.

Well the only reason I know this issue exists is because it was logged under system.

2014-03-17 13:28:41,928 (bfc) :  DEBUG (runtime:814) - Found route matching /system/services/url/lookup
2014-03-17 13:28:41,928 (bfc) :  DEBUG (services:23) - Looking up URL 'http://www.youtube.com/watch?v=JiFnci6qPwE'
2014-03-17 13:28:41,930 (bfc) :  DEBUG (services:615) - Found a service matching 'http://www.youtube.com/watch?v=JiFnci6qPwE' - YouTube (com.plexapp.plugins.youtube)
2014-03-17 13:28:41,934 (bfc) :  DEBUG (runtime:49) - Received packed state data (80 bytes)
2014-03-17 13:28:41,937 (bfc) :  DEBUG (services:615) - Found a service matching 'http://www.youtube.com/watch?v=JiFnci6qPwE' - YouTube (com.plexapp.plugins.youtube)
2014-03-17 13:28:41,940 (bfc) :  DEBUG (runtime:49) - Received packed state data (80 bytes)
2014-03-17 13:28:41,953 (bfc) :  DEBUG (networking:172) - Requesting 'http://gdata.youtube.com/feeds/api/videos/JiFnci6qPwE?v=2&alt=jsonc'
2014-03-17 13:28:42,051 (bfc) :  ERROR (networking:223) - Error opening URL 'http://gdata.youtube.com/feeds/api/videos/JiFnci6qPwE?v=2&alt=jsonc'
2014-03-17 13:28:42,052 (bfc) :  CRITICAL (core:561) - Exception when calling function 'MetadataObjectForURL' (most recent call last):
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\code\sandbox.py", line 297, in call_named_function
    result = f(*args, **kwargs)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Services.bundle\Contents\Service Sets\com.plexapp.plugins.youtube\URL\YouTube\ServiceCode.pys", line 112, in MetadataObjectForURL
    raise Ex.MediaNotAuthorized
MediaNotAuthorized: (2004, 'You are not authorized to access this media.')

2014-03-17 13:28:42,052 (bfc) : CRITICAL (services:744) - Exception calling function in URL service “YouTube” (com.plexapp.plugins.youtube)
2014-03-17 13:28:42,055 (bfc) : CRITICAL (core:561) - Exception (most recent call last):
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\runtime.py”, line 843, in handle_request
result = f(**d)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\handlers\services.py”, line 26, in url_lookup
c = self._core.services.metadata_object_for_url(url, in_container=True)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py”, line 724, in metadata_object_for_url
return self._get_result_from_function_for_url(self.metadata_object_for_url_from_service, url, do_normalization, dict(add_items_automatically = add_items_automatically, allow_deferred = allow_deferred, in_container = in_container))
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py”, line 740, in _get_result_from_function_for_url
result = func(url, service, **kwargs)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py”, line 641, in metadata_object_for_url_from_service
metadata = self._call_named_function_in_service(METADATA_OBJECT_FUNCTION_NAME, service, )
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py”, line 588, in _call_named_function_in_service
return self._call_named_function_in_sandbox(service.sandbox, fname, None, f_args, f_kwargs, allow_deferred, raise_exceptions, f_optional)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py”, line 572, in _call_named_function_in_sandbox
result = sandbox.call_named_function(fname, allow_deferred=allow_deferred, raise_exceptions=raise_exceptions, args=f_args, kwargs=f_kwargs, mod_name=mod_name, optional_kwargs=f_optional)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\code\sandbox.py”, line 297, in call_named_function
result = f(*args, **kwargs)
File “C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Services.bundle\Contents\Service Sets\com.plexapp.plugins.youtube\URL\YouTube\ServiceCode.pys”, line 112, in MetadataObjectForURL
raise Ex.MediaNotAuthorized
MediaNotAuthorized: (2004, ‘You are not authorized to access this media.’)

This does not occur inside of my scripts log at all, just the com.plexapp.system.log file and nothing I do from within my __init__.py seems to catch them?

Initially I was going to write this script without services, then add them in afterwards one at a time as the site I am using embeds players from numerous sources, some of which are not currently compatible. Most of the sources right now are from YouTube, a bunch from Vimeo, and the rest I haven't fully gotten to yet but these random ones are not a huge concern right now.

Currently I am focusing on YouTube and I'd like to add the the objects to the container, and then when pressed have a popup stating it failed due to MediaNotAuthorized, MediaNotAvailable, etc. type errors.

I'm pretty close to something releasable but I'm not really comfortable leaving it to just fail without a cause, especially when as the channel creator I do not have any control on the videos.

Just figure the more detailed I am, the less I'll have to deal with in the long run. ;)

The site I am working on is: http://www.documentaryheaven.com/

Those exceptions _should_ be handled directly by the client app. You are not responsible for catching them (nor could you) and notifying the user. If the client app you are testing with does not return an error message, then we'll need to pester the relevant developer to fix it.

What app(s) are you testing with?

For what it's worth I don't think I've ever seen any client actually catch one of these exceptions when I've used them for anything (aside from spitting out a generic error that something couldn't be played, listed, etc).

Those exceptions _should_ be handled directly by the client app. You are not responsible for catching them (nor could you) and notifying the user. If the client app you are testing with does not return an error message, then we'll need to pester the relevant developer to fix it.

What app(s) are you testing with?

Its a Channel for http://www.documentaryheaven.com.

Before worrying too much about it, I'm pretty sure an overhaul on my script will take care of the issue. It's a first run so there is a lot of junk currently built up and it's well overdue. I'm pretty sure it's in my try/except statements they were working fine without the new changes. At it's base, I already have a version that functions well but it simply walks the site per page which is sluggish. This only started happening when I implemented some logic to store metadata to Data() storage for quicker access. It just threw me off because of how they showed up in the system log instead of the channel log (I'm still getting a grip on everything).

With regards to the who's responsible for handling it...I think I might not have explained myself properly. ;)

What I'm looking to do is exactly what Mikedm139 suggested with using the ObjectContainer to relay the message to the user. In my case, I still have access to the metadata from DocuHeaven so I can still make it look right regardless of the url's accessibility. I'd prefer to create the item with DocuHeaven's metadata (Thumb, title, etc) and have it popup a header/message with an error on click, instead of submitting a dead/unauthorized url; just seems more user-friendly that way. For me to simply skip a video would have my channel looking buggy as it will not represent what is seen on the site (plus it would interfere with my custom page/metadata storage logic, for the moment).

That said, there is another error issue I am unsure of how to deal with. When a URL Service cannot be found for a given URL I receive this in my channel's log:

2014-03-19 15:26:10,177 (280) :  DEBUG (services:602) - No service found for URL 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,180 (280) :  DEBUG (services:617) - No matching services found for 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,183 (280) :  DEBUG (runtime:49) - Received packed state data (1036 bytes)
2014-03-19 15:26:10,187 (280) :  DEBUG (services:602) - No service found for URL 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,187 (280) :  CRITICAL (core:561) - Exception when constructing response (most recent call last):
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\runtime.py", line 945, in construct_response
    el = result._to_xml()
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 613, in _to_xml
    el = Framework.modelling.objects.ModelInterfaceObjectContainer._to_xml(self)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 382, in _to_xml
    root = Container._to_xml(self)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 139, in _to_xml
    self._append_children(root, self._objects)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 145, in _append_children
    el = obj._to_xml()
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 531, in _to_xml
    if self._core.services.function_in_service_is_deferred(Framework.components.services.MEDIA_OBJECTS_FUNCTION_NAME, service):
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py", line 556, in function_in_service_is_deferred
    service.sandbox.context.import_values(values)
AttributeError: 'NoneType' object has no attribute 'sandbox'

2014-03-19 15:26:10,190 (280) : DEBUG (runtime:1021) - Unable to handle response type: <class ‘Framework.modelling.objects.MediaContainer’>
2014-03-19 15:26:10,191 (280) : DEBUG (runtime:106) - Sending packed state data (1074 bytes)
2014-03-19 15:26:10,193 (280) : DEBUG (runtime:918) - Response: [500] MediaContainer, 0 bytes

Once this issue occurs my channel errors, and I am not sure where to go from there?

Is there a way to check which URL Services are available ahead of time so I can handle them before I add them to the container? Or is there another Exception that I can catch when this happens? It just seems like the right time to sub the video container with the custom error with header/message.

Thanks again!

Might wanna check for variables been empty/Not Initialized

if not myVariable:

DoStuff

return

/T

Its a Channel for http://www.documentaryheaven.com.

Before worrying too much about it, I'm pretty sure an overhaul on my script will take care of the issue. It's a first run so there is a lot of junk currently built up and it's well overdue. I'm pretty sure it's in my try/except statements they were working fine without the new changes. At it's base, I already have a version that functions well but it simply walks the site per page which is sluggish. This only started happening when I implemented some logic to store metadata to Data() storage for quicker access. It just threw me off because of how they showed up in the system log instead of the channel log (I'm still getting a grip on everything).

With regards to the who's responsible for handling it...I think I might not have explained myself properly. ;)

What I'm looking to do is exactly what Mikedm139 suggested with using the ObjectContainer to relay the message to the user. In my case, I still have access to the metadata from DocuHeaven so I can still make it look right regardless of the url's accessibility. I'd prefer to create the item with DocuHeaven's metadata (Thumb, title, etc) and have it popup a header/message with an error on click, instead of submitting a dead/unauthorized url; just seems more user-friendly that way. For me to simply skip a video would have my channel looking buggy as it will not represent what is seen on the site (plus it would interfere with my custom page/metadata storage logic, for the moment).

That said, there is another error issue I am unsure of how to deal with. When a URL Service cannot be found for a given URL I receive this in my channel's log:

2014-03-19 15:26:10,177 (280) :  DEBUG (services:602) - No service found for URL 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,180 (280) :  DEBUG (services:617) - No matching services found for 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,183 (280) :  DEBUG (runtime:49) - Received packed state data (1036 bytes)
2014-03-19 15:26:10,187 (280) :  DEBUG (services:602) - No service found for URL 'http://joost.com/embed/3128xef'
2014-03-19 15:26:10,187 (280) :  CRITICAL (core:561) - Exception when constructing response (most recent call last):
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\runtime.py", line 945, in construct_response
    el = result._to_xml()
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 613, in _to_xml
    el = Framework.modelling.objects.ModelInterfaceObjectContainer._to_xml(self)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 382, in _to_xml
    root = Container._to_xml(self)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 139, in _to_xml
    self._append_children(root, self._objects)
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 145, in _append_children
    el = obj._to_xml()
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 531, in _to_xml
    if self._core.services.function_in_service_is_deferred(Framework.components.services.MEDIA_OBJECTS_FUNCTION_NAME, service):
  File "C:\Users\No1\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py", line 556, in function_in_service_is_deferred
    service.sandbox.context.import_values(values)
AttributeError: 'NoneType' object has no attribute 'sandbox'

2014-03-19 15:26:10,190 (280) : DEBUG (runtime:1021) - Unable to handle response type: <class ‘Framework.modelling.objects.MediaContainer’>
2014-03-19 15:26:10,191 (280) : DEBUG (runtime:106) - Sending packed state data (1074 bytes)
2014-03-19 15:26:10,193 (280) : DEBUG (runtime:918) - Response: [500] MediaContainer, 0 bytes

Once this issue occurs my channel errors, and I am not sure where to go from there?

Is there a way to check which URL Services are available ahead of time so I can handle them before I add them to the container? Or is there another Exception that I can catch when this happens? It just seems like the right time to sub the video container with the custom error with header/message.

Thanks again!

You can check for existing URL Services using this code snippet:

URLService.ServiceIdentifierForURL(url_to_check)

On a more general note, there are obviously some shortcomings in the existing framework documentation. Because of that, several of us have made an effort to compile notes about useful methods which are available but absent from the docs. The sticky post is here. The code snippet above is taken directly from the compiled notes ;)

@dane22 - I was under the assumption that the lines above the actual error, referring to the joosk url was the offender? Or are these messages threaded and not necessarily in the correct order? Every time I initiated the error, it fails at the same place so it does (by reaction) appear to be related?

@Mikedm139 - That "hidden" function does looks like it might just solve the prob :) Thank you for that link, I will definitely check that out!

@dane22 - I was under the assumption that the lines above the actual error, referring to the joosk url was the offender? Or are these messages threaded and not necessarily in the correct order? Every time I initiated the error, it fails at the same place so it does (by reaction) appear to be related?

Correct, but using my methode, it's fast to check for the 'result' object

But when that's said, Mike's way is indeed the official way to check with an Un-Official call :D

I'm just a lazy ■■■■■■■, and use my method when trying to save coding eq. time, and outcome is the same, or?

/T

Edited: Changed 'el' to 'result'

Correct, but using my methode, it's fast to check for the 'result' object

But when that's said, Mike's way is indeed the official way to check with an Un-Official call :D

I'm just a lazy ■■■■■■■, and use my method when trying to save coding eq. time, and outcome is the same, or?

/T

Edited: Changed 'el' to 'result'

I'm usually the same but in this case I'm putting a bit more time into it to get a better grip....then I can be lazy again! ;)

But in all honesty the fact that it says NoneType is odd as I default to an empty string if a url is not found? It "should" not run into a NoneType if it is indeed the url variable as implied. With the official way I can easy figure out the issue and add a custom object to the container instead of one that will invoke the url service. That said I just realized that the little trick above with the container might not do what I need as I need to invoke the header/message on an item click, not set it on the whole container. :(

Just a thought but can you invoke a "back" press programmatically? If so, I think given that an object cannot invoke a header/message, I could invoke a callback with a directory object, and have the following container host the header/message instead. Then (provided you can invoke back, and the time module is available) have it auto-back to the prev media list after X amount of seconds...

Also is it safe to assume that if there is no url service, the video will not be able to play? I don't want to limit out the urls if there is a chance they might still play :P

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.