# Path: plex/objects/core/base.py
# class Property(object):
#     helpers = Interface.helpers
# 
#     def __init__(self, name=None, type=None, resolver=None):
#         self.name = name
#         self.type = type
#         self.resolver = resolver
# 
#     def value(self, descriptor, client, key, node, keys_used):
#         if self.resolver is not None:
#             return self.value_func(descriptor, client, key, node, keys_used)
# 
#         return self.value_node(descriptor, key, node, keys_used)
# 
#     def value_node(self, descriptor, key, node, keys_used):
#         value = self.helpers.get(node, key)
# 
#         if value is None:
#             return None
# 
#         keys_used.append(key.lower())
# 
#         try:
#             return self.value_convert(value)
#         except Exception as ex:
#             log.warn('[%s] Unable to parse property %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
#     def value_convert(self, value):
#         if not self.type:
#             return value
# 
#         types = self.type if isinstance(self.type, collections.Iterable) else [self.type]
#         result = value
# 
#         for target_type in types:
#             try:
#                 result = target_type(result)
#             except Exception as ex:
#                 six.reraise(ex, None, sys.exc_info()[2])
# 
#         return result
# 
#     def value_func(self, descriptor, client, key, node, keys_used):
#         func = self.resolver()
# 
#         try:
#             keys, value = func(client, node)
# 
#             keys_used.extend([k.lower() for k in keys])
#             return value
#         except Exception as ex:
#             log.warn('[%s] Exception raised in value function for %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
# Path: plex/objects/library/metadata/base.py
# class Metadata(Descriptor):
#     section = Property(resolver=lambda: Metadata.construct_section)
# 
#     key = Property
#     guid = Property
#     rating_key = Property('ratingKey')
#     extra_key = Property('primaryExtraKey')
# 
#     title = Property
#     title_sort = Property('titleSort')
#     title_sort_saved = Property('titleSortSaved')
#     title_original = Property('originalTitle')
# 
#     audience_rating = Property('audienceRating', float)
#     audience_rating_image = Property('audienceRatingImage')
# 
#     content_rating = Property('contentRating')
#     content_rating_age = Property('contentRatingAge', int)
# 
#     rating = Property(type=float)
#     rating_count = Property('ratingCount')
#     rating_image = Property('ratingImage')
# 
#     studio = Property
#     summary = Property
#     tagline = Property
#     year = Property(type=int)
# 
#     thumb = Property
# 
#     source_icon = Property('sourceIcon')
#     source_title = Property('sourceTitle')
#     url = Property('url')
# 
#     deferred = Property(type=(int, bool))
# 
#     added_at = Property('addedAt', int)
#     created_at_accuracy = Property('createdAtAccuracy')
#     created_at_tzoffset = Property('createdAtTZOffset', int)
#     deleted_at = Property('deletedAt', int)
#     first_scan_added_at = Property('firstScanAddedAt', int)
#     last_viewed_at = Property('lastViewedAt', int)
#     originally_available_at = Property('originallyAvailableAt')
# 
#     @staticmethod
#     def construct_section(client, node):
#         attribute_map = {
#             'key': 'librarySectionID',
#             'uuid': 'librarySectionUUID',
#             'title': 'librarySectionTitle'
#         }
# 
#         return Section.construct(client, node, attribute_map, child=True)
# 
# Path: plex/objects/library/metadata/photo.py
# class PhotoAlbum(Directory, Metadata):
#     index = Property(type=int)
# 
#     def __repr__(self):
#         return '<PhotoAlbum %r>' % self.title
# 
# Path: plex/objects/library/video.py
# class Video(Directory, SessionMixin):
#     director = Property(resolver=lambda: Director.from_node)
#     media = Property(resolver=lambda: Media.from_node)
#     writers = Property(resolver=lambda: Writer.from_node)
# 
#     view_count = Property('viewCount', int)
#     view_offset = Property('viewOffset', int)
# 
#     chapter_images_stale = Property('chapterImagesStale', (int, bool))
#     chapter_source = Property('chapterSource')
#     duration = Property(type=int)
# 
#     @property
#     def seen(self):
#         return self.view_count and self.view_count >= 1


from plex.objects.core.base import Property
from plex.objects.library.metadata.base import Metadata
from plex.objects.library.metadata.photo import PhotoAlbum
from plex.objects.library.video import Video
        return '<Clip %r>' % self.title

    @staticmethod
    def construct_grandparent(client, node):
        attribute_map = {
            'key':          'grandparentKey',
            'ratingKey':    'grandparentRatingKey',
            'index':        'grandparentIndex',

            'title':        'grandparentTitle',

            'art':          'grandparentArt',
            'thumb':        'grandparentThumb'
        }

        return PhotoAlbum.construct(client, node, attribute_map, child=True)

    @staticmethod
    def construct_parent(client, node):
        attribute_map = {
            'key':          'parentKey',
            'ratingKey':    'parentRatingKey',
            'index':        'parentIndex',

            'title':        'parentTitle',

            'art':          'parentArt',
            'thumb':        'parentThumb'
        }


# Path: plex/objects/core/base.py
# class Property(object):
#     helpers = Interface.helpers
# 
#     def __init__(self, name=None, type=None, resolver=None):
#         self.name = name
#         self.type = type
#         self.resolver = resolver
# 
#     def value(self, descriptor, client, key, node, keys_used):
#         if self.resolver is not None:
#             return self.value_func(descriptor, client, key, node, keys_used)
# 
#         return self.value_node(descriptor, key, node, keys_used)
# 
#     def value_node(self, descriptor, key, node, keys_used):
#         value = self.helpers.get(node, key)
# 
#         if value is None:
#             return None
# 
#         keys_used.append(key.lower())
# 
#         try:
#             return self.value_convert(value)
#         except Exception as ex:
#             log.warn('[%s] Unable to parse property %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
#     def value_convert(self, value):
#         if not self.type:
#             return value
# 
#         types = self.type if isinstance(self.type, collections.Iterable) else [self.type]
#         result = value
# 
#         for target_type in types:
#             try:
#                 result = target_type(result)
#             except Exception as ex:
#                 six.reraise(ex, None, sys.exc_info()[2])
# 
#         return result
# 
#     def value_func(self, descriptor, client, key, node, keys_used):
#         func = self.resolver()
# 
#         try:
#             keys, value = func(client, node)
# 
#             keys_used.extend([k.lower() for k in keys])
#             return value
#         except Exception as ex:
#             log.warn('[%s] Exception raised in value function for %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
# Path: plex/objects/library/metadata/base.py
# class Metadata(Descriptor):
#     section = Property(resolver=lambda: Metadata.construct_section)
# 
#     key = Property
#     guid = Property
#     rating_key = Property('ratingKey')
#     extra_key = Property('primaryExtraKey')
# 
#     title = Property
#     title_sort = Property('titleSort')
#     title_sort_saved = Property('titleSortSaved')
#     title_original = Property('originalTitle')
# 
#     audience_rating = Property('audienceRating', float)
#     audience_rating_image = Property('audienceRatingImage')
# 
#     content_rating = Property('contentRating')
#     content_rating_age = Property('contentRatingAge', int)
# 
#     rating = Property(type=float)
#     rating_count = Property('ratingCount')
#     rating_image = Property('ratingImage')
# 
#     studio = Property
#     summary = Property
#     tagline = Property
#     year = Property(type=int)
# 
#     thumb = Property
# 
#     source_icon = Property('sourceIcon')
#     source_title = Property('sourceTitle')
#     url = Property('url')
# 
#     deferred = Property(type=(int, bool))
# 
#     added_at = Property('addedAt', int)
#     created_at_accuracy = Property('createdAtAccuracy')
#     created_at_tzoffset = Property('createdAtTZOffset', int)
#     deleted_at = Property('deletedAt', int)
#     first_scan_added_at = Property('firstScanAddedAt', int)
#     last_viewed_at = Property('lastViewedAt', int)
#     originally_available_at = Property('originallyAvailableAt')
# 
#     @staticmethod
#     def construct_section(client, node):
#         attribute_map = {
#             'key': 'librarySectionID',
#             'uuid': 'librarySectionUUID',
#             'title': 'librarySectionTitle'
#         }
# 
#         return Section.construct(client, node, attribute_map, child=True)
# 
# Path: plex/objects/library/metadata/photo.py
# class PhotoAlbum(Directory, Metadata):
#     index = Property(type=int)
# 
#     def __repr__(self):
#         return '<PhotoAlbum %r>' % self.title
# 
# Path: plex/objects/library/video.py
# class Video(Directory, SessionMixin):
#     director = Property(resolver=lambda: Director.from_node)
#     media = Property(resolver=lambda: Media.from_node)
#     writers = Property(resolver=lambda: Writer.from_node)
# 
#     view_count = Property('viewCount', int)
#     view_offset = Property('viewOffset', int)
# 
#     chapter_images_stale = Property('chapterImagesStale', (int, bool))
#     chapter_source = Property('chapterSource')
#     duration = Property(type=int)
# 
#     @property
#     def seen(self):
#         return self.view_count and self.view_count >= 1


# Path: plex/objects/library/metadata/clip.py
from plex.objects.core.base import Property
from plex.objects.library.metadata.base import Metadata
from plex.objects.library.metadata.photo import PhotoAlbum
from plex.objects.library.video import Video

        return '<Clip %r>' % self.title

    @staticmethod
    def construct_grandparent(client, node):
        attribute_map = {
            'key':          'grandparentKey',
            'ratingKey':    'grandparentRatingKey',
            'index':        'grandparentIndex',

            'title':        'grandparentTitle',

            'art':          'grandparentArt',
            'thumb':        'grandparentThumb'
        }

        return PhotoAlbum.construct(client, node, attribute_map, child=True)

    @staticmethod
    def construct_parent(client, node):
        attribute_map = {
            'key':          'parentKey',
            'ratingKey':    'parentRatingKey',
            'index':        'parentIndex',

            'title':        'parentTitle',

            'art':          'parentArt',
            'thumb':        'parentThumb'
        }


        return PhotoAlbum.construct(client, node, attribute_map, child=True)