<commit_before>from subprocess import check_call
import datetime
import itertools
import logging
import os

import concurrent.futures

from sgfs import SGFS
from sgsession import Session, Entity
from shotgun_api3.shotgun import Fault as ShotgunFault

from . import utils
from . import versions


log = logging.getLogger(__name__)


_kwarg_to_field = {
    'created_by': 'created_by',
    'description': 'description',
    'frames_path': 'sg_path_to_frames',
    'movie_path': 'sg_path_to_movie',
    'movie_url': 'sg_qt',
    'source_publishes': 'sg_source_publishes',
    'trigger_event': 'sg_trigger_event_id',
}


class Publisher(object):
    
    """A publishing assistant.
    
    This object encapsulates the logic for the required two-stage creation cycle
    of a Shotgun ``PublishEvent``.
    
    This object is used as a context manager such that it will cleanup
    the first stage of the commit if there is an exception::
    
        >>> with sgpublish.Publisher(link=task, type="maya_scene", code=name,
        ...         ) as publisher:
        ...     publisher.add_file(scene_file)
    
    The names of the parameters and attributes are largely the same as that of
    the underlying ``PublishEvent`` itself, albeit with the ``"sg_"`` prefix
    removed.
    
    :param link: The Shotgun entity to attach to.
    :type link: :class:`python:dict` or :class:`~sgsession.entity.Entity`
    
    :param str type: A code for the type of publish. This is significant to the
        user and publish handlers.
    
    :param str code: A name for the stream of publishes.
    
    :param path: The directory to create for the publish. If ``None``, this will
        be generated via the ``"{type}_publish"`` :class:`sgfs.Template
        <sgfs.template.Template>` found for the given ``link``.
    :type path: str or None
    
    :param str description: The publish's description; can be provided via an
        attribute before :meth:`.commit`.
    
    :param created_by: A Shotgun ``HumanUser`` for the publish to be attached to.
        ``None`` will result in a guess via :func:`.guess_shotgun_user`.
    :type created_by: :class:`~sgsession.entity.Entity`, :class:`dict`, or None
    
    :param sgfs: The SGFS to use. Will be pulled from the link's session if not
        provided.
    :type sgfs: :class:`~sgfs.sgfs.SGFS` or None
    
    """

    def __init__(self, link=None, type=None, name=None, version=None, parent=None,
        directory=None, sgfs=None, template=None, **kwargs
    ):
        
        if template:

            to_fetch = ['sg_link', 'sg_type', 'code']
            to_fetch.extend(_kwarg_to_field.itervalues())
            template.fetch(to_fetch)

            tpl_link, tpl_type, tpl_name = template.get(('sg_link', 'sg_type', 'code'))
            link = link or tpl_link
            type = type or tpl_type
            name = name or tpl_name

            kwargs.setdefault('source_publishes', [template])
            for key, field in _kwarg_to_field.iteritems():
                kwargs.setdefault(key, template.get(field))

        if not (link and type and name):
            raise ValueError('requires link, type, and name')

        self.sgfs = sgfs or (SGFS(session=link.session) if isinstance(link, Entity) else SGFS())

        self._type = str(type)
        self._link = self.sgfs.session.merge(link)
        self._name = str(name)
        self._parent = parent

        # Get information about the promotion for review.
        self._review_version_entity = None
        self._review_version_fields = kwargs.pop('review_version_fields', None)

        # To only allow us to commit once.
        self._committed = False
        
        # Will be set into the tag.
        self.metadata = {}
        
        # Files to copy on commit; (src_path, dst_path)
        self._files = []
        
        # Set attributes from kwargs.<commit_msg>Get thumbnail path from template via SGFS tags<commit_after>from subprocess import check_call
import datetime
import itertools
import logging
import os

import concurrent.futures

from sgfs import SGFS
from sgsession import Session, Entity
from shotgun_api3.shotgun import Fault as ShotgunFault

from . import utils
from . import versions


log = logging.getLogger(__name__)


_kwarg_to_field = {
    'created_by': 'created_by',
    'description': 'description',
    'frames_path': 'sg_path_to_frames',
    'movie_path': 'sg_path_to_movie',
    'movie_url': 'sg_qt',
    'source_publishes': 'sg_source_publishes',
    'trigger_event': 'sg_trigger_event_id',
}


class Publisher(object):
    
    """A publishing assistant.
    
    This object encapsulates the logic for the required two-stage creation cycle
    of a Shotgun ``PublishEvent``.
    
    This object is used as a context manager such that it will cleanup
    the first stage of the commit if there is an exception::
    
        >>> with sgpublish.Publisher(link=task, type="maya_scene", code=name,
        ...         ) as publisher:
        ...     publisher.add_file(scene_file)
    
    The names of the parameters and attributes are largely the same as that of
    the underlying ``PublishEvent`` itself, albeit with the ``"sg_"`` prefix
    removed.
    
    :param link: The Shotgun entity to attach to.
    :type link: :class:`python:dict` or :class:`~sgsession.entity.Entity`
    
    :param str type: A code for the type of publish. This is significant to the
        user and publish handlers.
    
    :param str code: A name for the stream of publishes.
    
    :param path: The directory to create for the publish. If ``None``, this will
        be generated via the ``"{type}_publish"`` :class:`sgfs.Template
        <sgfs.template.Template>` found for the given ``link``.
    :type path: str or None
    
    :param str description: The publish's description; can be provided via an
        attribute before :meth:`.commit`.
    
    :param created_by: A Shotgun ``HumanUser`` for the publish to be attached to.
        ``None`` will result in a guess via :func:`.guess_shotgun_user`.
    :type created_by: :class:`~sgsession.entity.Entity`, :class:`dict`, or None
    
    :param sgfs: The SGFS to use. Will be pulled from the link's session if not
        provided.
    :type sgfs: :class:`~sgfs.sgfs.SGFS` or None
    
    """

    def __init__(self, link=None, type=None, name=None, version=None, parent=None,
        directory=None, sgfs=None, template=None, **kwargs
    ):
        
        if not sgfs:
            if template:
                sgfs = SGFS(session=template.session)
            elif link:
                sgfs = SGFS(session=link.session)
            else:
                sgfs = SGFS()
        self.sgfs = sgfs

        if template:

            to_fetch = ['sg_link', 'sg_type', 'code']
            to_fetch.extend(_kwarg_to_field.itervalues())
            template.fetch(to_fetch)

            tpl_link, tpl_type, tpl_name = template.get(('sg_link', 'sg_type', 'code'))
            link = link or tpl_link
            type = type or tpl_type
            name = name or tpl_name

            kwargs.setdefault('source_publishes', [template])
            for key, field in _kwarg_to_field.iteritems():
                kwargs.setdefault(key, template.get(field))

            if not kwargs.get('thumbnail_path'):
                # We certainly jump through a lot of hoops to do this...
                # Perhaps this should be sgfs.get_entity_tags(entity)
                publish_path = sgfs.path_for_entity(template)
                if publish_path:
                    tags = sgfs.get_directory_entity_tags(publish_path)
                    tags = [tag for tag in tags if tag['entity'] == template]
                    if tags:
                        meta = tags[0].get('sgpublish', {})
                        thumbnail = meta.get('thumbnail')
                        if thumbnail:
                            kwargs['thumbnail_path'] = thumbnail

        if not (link and type and name):
            raise ValueError('requires link, type, and name')

        self._type = str(type)
        self._link = self.sgfs.session.merge(link)
        self._name = str(name)
        self._parent = parent

        # Get information about the promotion for review.
        self._review_version_entity = None
        self._review_version_fields = kwargs.pop('review_version_fields', None)

        # To only allow us to commit once.
        self._committed = False
        
        # Will be set into the tag.
        self.metadata = {}
        
        # Files to copy on commit; (src_path, dst_path)
        self._files = []
        
        # Set attributes from kwargs.
{'fraction_non_alphanumeric': 0.09411764705882353, 'fraction_numerical': 0.00034602076124567473, 'mean_word_length': 2.3884329816334504, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '318255', 'n_tokens_mistral': 2566, 'n_tokens_neox': 2487, 'n_words': 809}