# Copyright 2010 Google Inc.
# Copyright (c) 2011, Nexenta Systems Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import boto
import os
import sys
import textwrap
from boto.s3.deletemarker import DeleteMarker
from boto.exception import BotoClientError
from boto.exception import InvalidUriError

class StorageUri(object):
    """
    Base class for representing storage provider-independent bucket and
    object name with a shorthand URI-like syntax.

    This is an abstract class: the constructor cannot be called (throws an
    exception if you try).
    """

    connection = None
    # Optional args that can be set from one of the concrete subclass
    # constructors, to change connection behavior (e.g., to override
    # https_connection_factory).
    connection_args = None

    # Map of provider scheme ('s3' or 'gs') to AWSAuthConnection object. We
    # maintain a pool here in addition to the connection pool implemented
    # in AWSAuthConnection because the latter re-creates its connection pool
    # every time that class is instantiated (so the current pool is used to
    # avoid re-instantiating AWSAuthConnection).
    provider_pool = {}

    def __init__(self):
        """Uncallable constructor on abstract base StorageUri class.
        """
        raise BotoClientError('Attempt to instantiate abstract StorageUri '
                              'class')

    def __repr__(self):
        """Returns string representation of URI."""
        return self.uri

    def equals(self, uri):
        """Returns true if two URIs are equal."""
        return self.uri == uri.uri

    def check_response(self, resp, level, uri):
        if resp is None:
            raise InvalidUriError('\n'.join(textwrap.wrap(
                'Attempt to get %s for "%s" failed. This can happen if '
                'the URI refers to a non-existent object or if you meant to '
                'operate on a directory (e.g., leaving off -R option on gsutil '
                'cp, mv, or ls of a bucket)' % (level, uri), 80)))

    def _check_bucket_uri(self, function_name):
        if issubclass(type(self), BucketStorageUri) and not self.bucket_name:
            raise InvalidUriError(
                '%s on bucket-less URI (%s)' % (function_name, self.uri))

    def _check_object_uri(self, function_name):
        if issubclass(type(self), BucketStorageUri) and not self.object_name:
            raise InvalidUriError('%s on object-less URI (%s)' %
                                  (function_name, self.uri))

    def _warn_about_args(self, function_name, **args):
        for arg in args:
            if args[arg]:
                sys.stderr.write(
                    'Warning: %s ignores argument: %s=%s\n' %
                    (function_name, arg, str(args[arg])))

    def connect(self, access_key_id=None, secret_access_key=None, **kwargs):
        """
        Opens a connection to appropriate provider, depending on provider
        portion of URI. Requires Credentials defined in boto config file (see
        boto/pyami/config.py).
        @type storage_uri: StorageUri
        @param storage_uri: StorageUri specifying a bucket or a bucket+object
        @rtype: L{AWSAuthConnection<boto.gs.connection.AWSAuthConnection>}
        @return: A connection to storage service provider of the given URI.
        """
        connection_args = dict(self.connection_args or ())

        if (hasattr(self, 'suppress_consec_slashes') and
                'suppress_consec_slashes' not in connection_args):
            connection_args['suppress_consec_slashes'] = (
                self.suppress_consec_slashes)
        connection_args.update(kwargs)
        if not self.connection:
            if self.scheme in self.provider_pool:
                self.connection = self.provider_pool[self.scheme]
            elif self.scheme == 's3':
                from boto.s3.connection import S3Connection
                self.connection = S3Connection(access_key_id,
                                               secret_access_key,
                                               **connection_args)
                self.provider_pool[self.scheme] = self.connection
            elif self.scheme == 'gs':
                from boto.gs.connection import GSConnection
                # Use OrdinaryCallingFormat instead of boto-default
                # SubdomainCallingFormat because the latter changes the hostname
                # that's checked during cert validation for HTTPS connections,
                # which will fail cert validation (when cert validation is
                # enabled).
                #
                # The same is not true for S3's HTTPS certificates. In fact,
                # we don't want to do this for S3 because S3 requires the
                # subdomain to match the location of the bucket. If the proper
                # subdomain is not used, the server will return a 301 redirect
                # with no Location header.
                #
                # Note: the following import can't be moved up to the
                # start of this file else it causes a config import failure when
                # run from the resumable upload/download tests.
                from boto.s3.connection import OrdinaryCallingFormat
                connection_args['calling_format'] = OrdinaryCallingFormat()
                self.connection = GSConnection(access_key_id,
                                               secret_access_key,
                                               **connection_args)
                self.provider_pool[self.scheme] = self.connection
            elif self.scheme == 'file':
                from boto.file.connection import FileConnection
                self.connection = FileConnection(self)
            else:
                raise InvalidUriError('Unrecognized scheme "%s"' %
                                      self.scheme)
        self.connection.debug = self.debug
        return self.connection

    def has_version(self):
        return (issubclass(type(self), BucketStorageUri)
                and ((self.version_id is not None)
                     or (self.generation is not None)))

    def delete_key(self, validate=False, headers=None, version_id=None,
                   mfa_token=None):
        self._check_object_uri('delete_key')
        bucket = self.get_bucket(validate, headers)
        return bucket.delete_key(self.object_name, headers, version_id,
                                 mfa_token)

    def list_bucket(self, prefix='', delimiter='', headers=None,
                    all_versions=False):
        self._check_bucket_uri('list_bucket')
        bucket = self.get_bucket(headers=headers)
        if all_versions:
            return (v for v in bucket.list_versions(
                prefix=prefix, delimiter=delimiter, headers=headers)
                if not isinstance(v, DeleteMarker))
        else:
            return bucket.list(prefix=prefix, delimiter=delimiter,
                               headers=headers)

    def get_all_keys(self, validate=False, headers=None, prefix=None):
        bucket = self.get_bucket(validate, headers)
        return bucket.get_all_keys(headers)

    def get_bucket(self, validate=False, headers=None):
        self._check_bucket_uri('get_bucket')
        conn = self.connect()
        bucket = conn.get_bucket(self.bucket_name, validate, headers)
        self.check_response(bucket, 'bucket', self.uri)
        return bucket

    def get_key(self, validate=False, headers=None, version_id=None):
        self._check_object_uri('get_key')
        bucket = self.get_bucket(validate, headers)
        key = bucket.get_key(self.object_name, headers, version_id)
        self.check_response(key, 'key', self.uri)
        return key

    def new_key(self, validate=False, headers=None):
        self._check_object_uri('new_key')
        bucket = self.get_bucket(validate, headers)
        return bucket.new_key(self.object_name)

    def get_contents_to_stream(self, fp, headers=None, version_id=None):
        self._check_object_uri('get_key')
        self._warn_about_args('get_key', validate=False)
        key = self.get_key(None, headers)
        self.check_response(key, 'key', self.uri)
        return key.get_contents_to_file(fp, headers, version_id=version_id)

    def get_contents_to_file(self, fp, headers=None, cb=None, num_cb=10,
                             torrent=False, version_id=None,
                             res_download_handler=None, response_headers=None,
                             hash_algs=None):
        self._check_object_uri('get_contents_to_file')
        key = self.get_key(None, headers)
        self.check_response(key, 'key', self.uri)
        if hash_algs:
            key.get_contents_to_file(fp, headers, cb, num_cb, torrent,
                                     version_id, res_download_handler,
                                     response_headers,
                                     hash_algs=hash_algs)
        else:
            key.get_contents_to_file(fp, headers, cb, num_cb, torrent,
                                     version_id, res_download_handler,
                                     response_headers)

    def get_contents_as_string(self, validate=False, headers=None, cb=None,
                               num_cb=10, torrent=False, version_id=None):
        self._check_object_uri('get_contents_as_string')
        key = self.get_key(validate, headers)
        self.check_response(key, 'key', self.uri)
        return key.get_contents_as_string(headers, cb, num_cb, torrent,
                                          version_id)

    def acl_class(self):
        conn = self.connect()
        acl_class = conn.provider.acl_class
        self.check_response(acl_class, 'acl_class', self.uri)
        return acl_class

    def canned_acls(self):
        conn = self.connect()
        canned_acls = conn.provider.canned_acls
        self.check_response(canned_acls, 'canned_acls', self.uri)
        return canned_acls

class BucketStorageUri(StorageUri):
    """
    StorageUri subclass that handles bucket storage providers.
    Callers should instantiate this class by calling boto.storage_uri().
    """

    delim = '/'
    capabilities = set([])  # A set of additional capabilities.

    def __init__(self, scheme, bucket_name=None, object_name=None,
                 debug=0, connection_args=None, suppress_consec_slashes=True,
                 version_id=None, generation=None, is_latest=False):
        """Instantiate a BucketStorageUri from scheme,bucket,object tuple.

        @type scheme: string
        @param scheme: URI scheme naming the storage provider (gs, s3, etc.)
        @type bucket_name: string
        @param bucket_name: bucket name
        @type object_name: string
        @param object_name: object name, excluding generation/version.
        @type debug: int
        @param debug: debug level to pass in to connection (range 0..2)
        @type connection_args: map
        @param connection_args: optional map containing args to be
            passed to {S3,GS}Connection constructor (e.g., to override
            https_connection_factory).
        @param suppress_consec_slashes: If provided, controls whether
            consecutive slashes will be suppressed in key paths.
        @param version_id: Object version id (S3-specific).
        @param generation: Object generation number (GCS-specific).
        @param is_latest: boolean indicating that a versioned object is the
            current version

        After instantiation the components are available in the following
        fields: scheme, bucket_name, object_name, version_id, generation,
        is_latest, versionless_uri, version_specific_uri, uri.
        Note: If instantiated without version info, the string representation
        for a URI stays versionless; similarly, if instantiated with version
        info, the string representation for a URI stays version-specific. If you
        call one of the uri.set_contents_from_xyz() methods, a specific object
        version will be created, and its version-specific URI string can be
        retrieved from version_specific_uri even if the URI was instantiated
        without version info.
        """

        self.scheme = scheme
        self.bucket_name = bucket_name
        self.object_name = object_name
        self.debug = debug
        if connection_args:
            self.connection_args = connection_args
        self.suppress_consec_slashes = suppress_consec_slashes
        self.version_id = version_id
        self.generation = generation and int(generation)
        self.is_latest = is_latest
        self.is_version_specific = bool(self.generation) or bool(version_id)
        self._build_uri_strings()

    def _build_uri_strings(self):
        if self.bucket_name and self.object_name:
            self.versionless_uri = '%s://%s/%s' % (self.scheme, self.bucket_name,
                                                   self.object_name)
            if self.generation:
                self.version_specific_uri = '%s#%s' % (self.versionless_uri,
                                                       self.generation)
            elif self.version_id:
                self.version_specific_uri = '%s#%s' % (
                    self.versionless_uri, self.version_id)
            if self.is_version_specific:
                self.uri = self.version_specific_uri
            else:
                self.uri = self.versionless_uri
        elif self.bucket_name:
            self.uri = ('%s://%s/' % (self.scheme, self.bucket_name))
        else:
            self.uri = ('%s://' % self.scheme)

    def _update_from_key(self, key):
        self._update_from_values(
            getattr(key, 'version_id', None),
            getattr(key, 'generation', None),
            getattr(key, 'is_latest', None),
            getattr(key, 'md5', None))

    def _update_from_values(self, version_id, generation, is_latest, md5):
        self.version_id = version_id
        self.generation = generation
        self.is_latest = is_latest
        self._build_uri_strings()
        self.md5 = md5

    def get_key(self, validate=False, headers=None, version_id=None):
        self._check_object_uri('get_key')
        bucket = self.get_bucket(validate, headers)
        if self.get_provider().name == 'aws':
            key = bucket.get_key(self.object_name, headers,
                                 version_id=(version_id or self.version_id))
        elif self.get_provider().name == 'google':
            key = bucket.get_key(self.object_name, headers,
                                 generation=self.generation)
        self.check_response(key, 'key', self.uri)
        return key

    def delete_key(self, validate=False, headers=None, version_id=None,
                   mfa_token=None):
        self._check_object_uri('delete_key')
        bucket = self.get_bucket(validate, headers)
        if self.get_provider().name == 'aws':
            version_id = version_id or self.version_id
            return bucket.delete_key(self.object_name, headers, version_id,
                                     mfa_token)
        elif self.get_provider().name == 'google':
            return bucket.delete_key(self.object_name, headers,
                                     generation=self.generation)

    def clone_replace_name(self, new_name):
        """Instantiate a BucketStorageUri from the current BucketStorageUri,
        but replacing the object_name.

        @type new_name: string
        @param new_name: new object name
        """
        self._check_bucket_uri('clone_replace_name')
        return BucketStorageUri(
            self.scheme, bucket_name=self.bucket_name, object_name=new_name,
            debug=self.debug,
            suppress_consec_slashes=self.suppress_consec_slashes)

    def clone_replace_key(self, key):
        """Instantiate a BucketStorageUri from the current BucketStorageUri, by
        replacing the object name with the object name and other metadata found
        in the given Key object (including generation).

        @type key: Key
        @param key: key for the new StorageUri to represent
        """
        self._check_bucket_uri('clone_replace_key')
        version_id = None
        generation = None
        is_latest = False
        if hasattr(key, 'version_id'):
            version_id = key.version_id
        if hasattr(key, 'generation'):
            generation = key.generation
        if hasattr(key, 'is_latest'):
            is_latest = key.is_latest

        return BucketStorageUri(
            key.provider.get_provider_name(),
            bucket_name=key.bucket.name,
            object_name=key.name,
            debug=self.debug,
            suppress_consec_slashes=self.suppress_consec_slashes,
            version_id=version_id,
            generation=generation,
            is_latest=is_latest)

    def get_acl(self, validate=False, headers=None, version_id=None):
        """returns a bucket's acl"""
        self._check_bucket_uri('get_acl')
        bucket = self.get_bucket(validate, headers)
        # This works for both bucket- and object- level ACLs (former passes
        # key_name=None):
        key_name = self.object_name or ''
        if self.get_provider().name == 'aws':
            version_id = version_id or self.version_id
            acl = bucket.get_acl(key_name, headers, version_id)
        else:
            acl = bucket.get_acl(key_name, headers, generation=self.generation)
        self.check_response(acl, 'acl', self.uri)
        return acl

    def get_def_acl(self, validate=False, headers=None):
        """returns a bucket's default object acl"""
        self._check_bucket_uri('get_def_acl')
        bucket = self.get_bucket(validate, headers)
        acl = bucket.get_def_acl(headers)
        self.check_response(acl, 'acl', self.uri)
        return acl

    def get_cors(self, validate=False, headers=None):
        """returns a bucket's CORS XML"""
        self._check_bucket_uri('get_cors')
        bucket = self.get_bucket(validate, headers)
        cors = bucket.get_cors(headers)
        self.check_response(cors, 'cors', self.uri)
        return cors

    def set_cors(self, cors, validate=False, headers=None):
        """sets or updates a bucket's CORS XML"""
        self._check_bucket_uri('set_cors ')
        bucket = self.get_bucket(validate, headers)
        if self.scheme == 's3':
          bucket.set_cors(cors, headers)
        else:
          bucket.set_cors(cors.to_xml(), headers)

    def get_location(self, validate=False, headers=None):
        self._check_bucket_uri('get_location')
        bucket = self.get_bucket(validate, headers)
        return bucket.get_location()

    def get_storage_class(self, validate=False, headers=None):
        self._check_bucket_uri('get_storage_class')
        # StorageClass is defined as a bucket and object param for GCS, but
        # only as a key param for S3.
        if self.scheme != 'gs':
            raise ValueError('get_storage_class() not supported for %s '
                             'URIs.' % self.scheme)
        bucket = self.get_bucket(validate, headers)
        return bucket.get_storage_class()

    def set_storage_class(self, storage_class, validate=False, headers=None):
        """Updates a bucket's storage class."""
        self._check_bucket_uri('set_storage_class')
        # StorageClass is defined as a bucket and object param for GCS, but
        # only as a key param for S3.
        if self.scheme != 'gs':
            raise ValueError('set_storage_class() not supported for %s '
                             'URIs.' % self.scheme)
        bucket = self.get_bucket(validate, headers)
        bucket.set_storage_class(storage_class, headers)

    def get_subresource(self, subresource, validate=False, headers=None,
                        version_id=None):
        self._check_bucket_uri('get_subresource')
        bucket = self.get_bucket(validate, headers)
        return bucket.get_subresource(subresource, self.object_name, headers,
                                      version_id)

    def add_group_email_grant(self, permission, email_address, recursive=False,
                              validate=False, headers=None):
        self._check_bucket_uri('add_group_email_grant')
        if self.scheme != 'gs':
            raise ValueError('add_group_email_grant() not supported for %s '
                             'URIs.' % self.scheme)
        if self.object_name:
            if recursive:
                raise ValueError('add_group_email_grant() on key-ful URI cannot '
                                 'specify recursive=True')
            key = self.get_key(validate, headers)
            self.check_response(key, 'key', self.uri)
            key.add_group_email_grant(permission, email_address, headers)
        elif self.bucket_name:
            bucket = self.get_bucket(validate, headers)
            bucket.add_group_email_grant(permission, email_address, recursive,
                                         headers)
        else:
            raise InvalidUriError('add_group_email_grant() on bucket-less URI '
                                  '%s' % self.uri)

    def add_email_grant(self, permission, email_address, recursive=False,
                        validate=False, headers=None):
        self._check_bucket_uri('add_email_grant')
        if not self.object_name:
            bucket = self.get_bucket(validate, headers)
            bucket.add_email_grant(permission, email_address, recursive,
                                   headers)
        else:
            key = self.get_key(validate, headers)
            self.check_response(key, 'key', self.uri)
            key.add_email_grant(permission, email_address)

    def add_user_grant(self, permission, user_id, recursive=False,
                       validate=False, headers=None):
        self._check_bucket_uri('add_user_grant')
        if not self.object_name:
            bucket = self.get_bucket(validate, headers)
            bucket.add_user_grant(permission, user_id, recursive, headers)
        else:
            key = self.get_key(validate, headers)
            self.check_response(key, 'key', self.uri)
            key.add_user_grant(permission, user_id)

    def list_grants(self, headers=None):
        self._check_bucket_uri('list_grants ')
        bucket = self.get_bucket(headers)
        return bucket.list_grants(headers)

    def is_file_uri(self):
        """Returns True if this URI names a file or directory."""
        return False

    def is_cloud_uri(self):
        """Returns True if this URI names a bucket or object."""
        return True

    def names_container(self):
        """
        Returns True if this URI names a directory or bucket. Will return
        False for bucket subdirs; providing bucket subdir semantics needs to
        be done by the caller (like gsutil does).
        """
        return bool(not self.object_name)

    def names_singleton(self):
        """Returns True if this URI names a file or object."""
        return bool(self.object_name)

    def names_directory(self):
        """Returns True if this URI names a directory."""
        return False

    def names_provider(self):
        """Returns True if this URI names a provider."""
        return bool(not self.bucket_name)

    def names_bucket(self):
        """Returns True if this URI names a bucket."""
        return bool(self.bucket_name) and bool(not self.object_name)

    def names_file(self):
        """Returns True if this URI names a file."""
        return False

    def names_object(self):
        """Returns True if this URI names an object."""
        return self.names_singleton()

    def is_stream(self):
        """Returns True if this URI represents input/output stream."""
        return False

    def create_bucket(self, headers=None, location='', policy=None,
                      storage_class=None):
        self._check_bucket_uri('create_bucket ')
        conn = self.connect()
        # Pass storage_class param only if this is a GCS bucket. (In S3 the
        # storage class is specified on the key object.)
        if self.scheme == 'gs':
            return conn.create_bucket(self.bucket_name, headers, location, policy,
                                      storage_class)
        else:
            return conn.create_bucket(self.bucket_name, headers, location, policy)

    def delete_bucket(self, headers=None):
        self._check_bucket_uri('delete_bucket')
        conn = self.connect()
        return conn.delete_bucket(self.bucket_name, headers)

    def get_all_buckets(self, headers=None):
        conn = self.connect()
        return conn.get_all_buckets(headers)

    def get_provider(self):
        conn = self.connect()
        provider = conn.provider
        self.check_response(provider, 'provider', self.uri)
        return provider

    def set_acl(self, acl_or_str, key_name='', validate=False, headers=None,
                version_id=None, if_generation=None, if_metageneration=None):
        """Sets or updates a bucket's ACL."""
        self._check_bucket_uri('set_acl')
        key_name = key_name or self.object_name or ''
        bucket = self.get_bucket(validate, headers)
        if self.generation:
            bucket.set_acl(
                acl_or_str, key_name, headers, generation=self.generation,
                if_generation=if_generation, if_metageneration=if_metageneration)
        else:
            version_id = version_id or self.version_id
            bucket.set_acl(acl_or_str, key_name, headers, version_id)

    def set_xml_acl(self, xmlstring, key_name='', validate=False, headers=None,
                    version_id=None, if_generation=None, if_metageneration=None):
        """Sets or updates a bucket's ACL with an XML string."""
        self._check_bucket_uri('set_xml_acl')
        key_name = key_name or self.object_name or ''
        bucket = self.get_bucket(validate, headers)
        if self.generation:
            bucket.set_xml_acl(
                xmlstring, key_name, headers, generation=self.generation,
                if_generation=if_generation, if_metageneration=if_metageneration)
        else:
            version_id = version_id or self.version_id
            bucket.set_xml_acl(xmlstring, key_name, headers,
                               version_id=version_id)

    def set_def_xml_acl(self, xmlstring, validate=False, headers=None):
        """Sets or updates a bucket's default object ACL with an XML string."""
        self._check_bucket_uri('set_def_xml_acl')
        self.get_bucket(validate, headers).set_def_xml_acl(xmlstring, headers)

    def set_def_acl(self, acl_or_str, validate=False, headers=None,
                    version_id=None):
        """Sets or updates a bucket's default object ACL."""
        self._check_bucket_uri('set_def_acl')
        self.get_bucket(validate, headers).set_def_acl(acl_or_str, headers)

    def set_canned_acl(self, acl_str, validate=False, headers=None,
                       version_id=None):
        """Sets or updates a bucket's acl to a predefined (canned) value."""
        self._check_object_uri('set_canned_acl')
        self._warn_about_args('set_canned_acl', version_id=version_id)
        key = self.get_key(validate, headers)
        self.check_response(key, 'key', self.uri)
        key.set_canned_acl(acl_str, headers)

    def set_def_canned_acl(self, acl_str, validate=False, headers=None,
                           version_id=None):
        """Sets or updates a bucket's default object acl to a predefined
           (canned) value."""
        self._check_bucket_uri('set_def_canned_acl ')
        key = self.get_key(validate, headers)
        self.check_response(key, 'key', self.uri)
        key.set_def_canned_acl(acl_str, headers, version_id)

    def set_subresource(self, subresource, value, validate=False, headers=None,
                        version_id=None):
        self._check_bucket_uri('set_subresource')
        bucket = self.get_bucket(validate, headers)
        bucket.set_subresource(subresource, value, self.object_name, headers,
                               version_id)

    def set_contents_from_string(self, s, headers=None, replace=True,
                                 cb=None, num_cb=10, policy=None, md5=None,
                                 reduced_redundancy=False):
        self._check_object_uri('set_contents_from_string')
        key = self.new_key(headers=headers)
        if self.scheme == 'gs':
            if reduced_redundancy:
                sys.stderr.write('Warning: GCS does not support '
                                 'reduced_redundancy; argument ignored by '
                                 'set_contents_from_string')
            result = key.set_contents_from_string(
                s, headers, replace, cb, num_cb, policy, md5)
        else:
            result = key.set_contents_from_string(
                s, headers, replace, cb, num_cb, policy, md5,
                reduced_redundancy)
        self._update_from_key(key)
        return result

    def set_contents_from_file(self, fp, headers=None, replace=True, cb=None,
                               num_cb=10, policy=None, md5=None, size=None,
                               rewind=False, res_upload_handler=None):
        self._check_object_uri('set_contents_from_file')
        key = self.new_key(headers=headers)
        if self.scheme == 'gs':
            result = key.set_contents_from_file(
                fp, headers, replace, cb, num_cb, policy, md5, size=size,
                rewind=rewind, res_upload_handler=res_upload_handler)
            if res_upload_handler:
                self._update_from_values(None, res_upload_handler.generation,
                                         None, md5)
        else:
            self._warn_about_args('set_contents_from_file',
                                  res_upload_handler=res_upload_handler)
            result = key.set_contents_from_file(
                fp, headers, replace, cb, num_cb, policy, md5, size=size,
                rewind=rewind)
        self._update_from_key(key)
        return result

    def set_contents_from_stream(self, fp, headers=None, replace=True, cb=None,
                                 policy=None, reduced_redundancy=False):
        self._check_object_uri('set_contents_from_stream')
        dst_key = self.new_key(False, headers)
        result = dst_key.set_contents_from_stream(
            fp, headers, replace, cb, policy=policy,
            reduced_redundancy=reduced_redundancy)
        self._update_from_key(dst_key)
        return result

    def copy_key(self, src_bucket_name, src_key_name, metadata=None,
                 src_version_id=None, storage_class='STANDARD',
                 preserve_acl=False, encrypt_key=False, headers=None,
                 query_args=None, src_generation=None):
        """Returns newly created key."""
        self._check_object_uri('copy_key')
        dst_bucket = self.get_bucket(validate=False, headers=headers)
        if src_generation:
            return dst_bucket.copy_key(
                new_key_name=self.object_name,
                src_bucket_name=src_bucket_name,
                src_key_name=src_key_name, metadata=metadata,
                storage_class=storage_class, preserve_acl=preserve_acl,
                encrypt_key=encrypt_key, headers=headers, query_args=query_args,
                src_generation=src_generation)
        else:
            return dst_bucket.copy_key(
                new_key_name=self.object_name,
                src_bucket_name=src_bucket_name, src_key_name=src_key_name,
                metadata=metadata, src_version_id=src_version_id,
                storage_class=storage_class, preserve_acl=preserve_acl,
                encrypt_key=encrypt_key, headers=headers, query_args=query_args)

    def enable_logging(self, target_bucket, target_prefix=None, validate=False,
                       headers=None, version_id=None):
        self._check_bucket_uri('enable_logging')
        bucket = self.get_bucket(validate, headers)
        bucket.enable_logging(target_bucket, target_prefix, headers=headers)

    def disable_logging(self, validate=False, headers=None, version_id=None):
        self._check_bucket_uri('disable_logging')
        bucket = self.get_bucket(validate, headers)
        bucket.disable_logging(headers=headers)

    def get_logging_config(self, validate=False, headers=None, version_id=None):
        self._check_bucket_uri('get_logging_config')
        bucket = self.get_bucket(validate, headers)
        return bucket.get_logging_config(headers=headers)

    def set_website_config(self, main_page_suffix=None, error_key=None,
                           validate=False, headers=None):
        self._check_bucket_uri('set_website_config')
        bucket = self.get_bucket(validate, headers)
        if not (main_page_suffix or error_key):
            bucket.delete_website_configuration(headers)
        else:
            bucket.configure_website(main_page_suffix, error_key, headers)

    def get_website_config(self, validate=False, headers=None):
        self._check_bucket_uri('get_website_config')
        bucket = self.get_bucket(validate, headers)
        return bucket.get_website_configuration(headers)

    def get_versioning_config(self, headers=None):
        self._check_bucket_uri('get_versioning_config')
        bucket = self.get_bucket(False, headers)
        return bucket.get_versioning_status(headers)

    def configure_versioning(self, enabled, headers=None):
        self._check_bucket_uri('configure_versioning')
        bucket = self.get_bucket(False, headers)
        return bucket.configure_versioning(enabled, headers)

    def set_metadata(self, metadata_plus, metadata_minus, preserve_acl,
                     headers=None):
        return self.get_key(False).set_remote_metadata(metadata_plus,
                                                       metadata_minus,
                                                       preserve_acl,
                                                       headers=headers)

    def compose(self, components, content_type=None, headers=None):
        self._check_object_uri('compose')
        component_keys = []
        for suri in components:
            component_keys.append(suri.new_key())
            component_keys[-1].generation = suri.generation
        self.generation = self.new_key().compose(
            component_keys, content_type=content_type, headers=headers)
        self._build_uri_strings()
        return self

    def get_lifecycle_config(self, validate=False, headers=None):
        """Returns a bucket's lifecycle configuration."""
        self._check_bucket_uri('get_lifecycle_config')
        bucket = self.get_bucket(validate, headers)
        lifecycle_config = bucket.get_lifecycle_config(headers)
        self.check_response(lifecycle_config, 'lifecycle', self.uri)
        return lifecycle_config

    def configure_lifecycle(self, lifecycle_config, validate=False,
                            headers=None):
        """Sets or updates a bucket's lifecycle configuration."""
        self._check_bucket_uri('configure_lifecycle')
        bucket = self.get_bucket(validate, headers)
        bucket.configure_lifecycle(lifecycle_config, headers)

    def exists(self, headers=None):
        """Returns True if the object exists or False if it doesn't"""
        if not self.object_name:
            raise InvalidUriError('exists on object-less URI (%s)' % self.uri)
        bucket = self.get_bucket()
        key = bucket.get_key(self.object_name, headers=headers)
        return bool(key)

class FileStorageUri(StorageUri):
    """
    StorageUri subclass that handles files in the local file system.
    Callers should instantiate this class by calling boto.storage_uri().

    See file/README about how we map StorageUri operations onto a file system.
    """

    delim = os.sep

    def __init__(self, object_name, debug, is_stream=False):
        """Instantiate a FileStorageUri from a path name.

        @type object_name: string
        @param object_name: object name
        @type debug: boolean
        @param debug: whether to enable debugging on this StorageUri

        After instantiation the components are available in the following
        fields: uri, scheme, bucket_name (always blank for this "anonymous"
        bucket), object_name.
        """

        self.scheme = 'file'
        self.bucket_name = ''
        self.object_name = object_name
        self.uri = 'file://' + object_name
        self.debug = debug
        self.stream = is_stream

    def clone_replace_name(self, new_name):
        """Instantiate a FileStorageUri from the current FileStorageUri,
        but replacing the object_name.

        @type new_name: string
        @param new_name: new object name
        """
        return FileStorageUri(new_name, self.debug, self.stream)

    def is_file_uri(self):
        """Returns True if this URI names a file or directory."""
        return True

    def is_cloud_uri(self):
        """Returns True if this URI names a bucket or object."""
        return False

    def names_container(self):
        """Returns True if this URI names a directory or bucket."""
        return self.names_directory()

    def names_singleton(self):
        """Returns True if this URI names a file (or stream) or object."""
        return not self.names_container()

    def names_directory(self):
        """Returns True if this URI names a directory."""
        if self.stream:
            return False
        return os.path.isdir(self.object_name)

    def names_provider(self):
        """Returns True if this URI names a provider."""
        return False

    def names_bucket(self):
        """Returns True if this URI names a bucket."""
        return False

    def names_file(self):
        """Returns True if this URI names a file."""
        return self.names_singleton()

    def names_object(self):
        """Returns True if this URI names an object."""
        return False

    def is_stream(self):
        """Returns True if this URI represents input/output stream.
        """
        return bool(self.stream)

    def close(self):
        """Closes the underlying file.
        """
        self.get_key().close()

    def exists(self, _headers_not_used=None):
        """Returns True if the file exists or False if it doesn't"""
        # The _headers_not_used parameter is ignored. It is only there to ensure
        # that this method's signature is identical to the exists method on the
        # BucketStorageUri class.
        return os.path.exists(self.object_name)


<?xml version='1.0' encoding='UTF-8'?>
<resources>
  <string name="AudioCDResourceProvider.Description">Kasuta audio CD radasid</string>
</resources>


package swift

import (
	"os"
)

// DynamicLargeObjectCreateFile represents an open static large object
type DynamicLargeObjectCreateFile struct {
	largeObjectCreateFile
}

// DynamicLargeObjectCreateFile creates a dynamic large object
// returning an object which satisfies io.Writer, io.Seeker, io.Closer
// and io.ReaderFrom.  The flags are as passes to the
// largeObjectCreate method.
func (c *Connection) DynamicLargeObjectCreateFile(opts *LargeObjectOpts) (LargeObjectFile, error) {
	lo, err := c.largeObjectCreate(opts)
	if err != nil {
		return nil, err
	}

	return withBuffer(opts, &DynamicLargeObjectCreateFile{
		largeObjectCreateFile: *lo,
	}), nil
}

// DynamicLargeObjectCreate creates or truncates an existing dynamic
// large object returning a writeable object.  This sets opts.Flags to
// an appropriate value before calling DynamicLargeObjectCreateFile
func (c *Connection) DynamicLargeObjectCreate(opts *LargeObjectOpts) (LargeObjectFile, error) {
	opts.Flags = os.O_TRUNC | os.O_CREATE
	return c.DynamicLargeObjectCreateFile(opts)
}

// DynamicLargeObjectDelete deletes a dynamic large object and all of its segments.
func (c *Connection) DynamicLargeObjectDelete(container string, path string) error {
	return c.LargeObjectDelete(container, path)
}

// DynamicLargeObjectMove moves a dynamic large object from srcContainer, srcObjectName to dstContainer, dstObjectName
func (c *Connection) DynamicLargeObjectMove(srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) error {
	info, headers, err := c.Object(dstContainer, srcObjectName)
	if err != nil {
		return err
	}

	segmentContainer, segmentPath := parseFullPath(headers["X-Object-Manifest"])
	if err := c.createDLOManifest(dstContainer, dstObjectName, segmentContainer+"/"+segmentPath, info.ContentType); err != nil {
		return err
	}

	if err := c.ObjectDelete(srcContainer, srcObjectName); err != nil {
		return err
	}

	return nil
}

// createDLOManifest creates a dynamic large object manifest
func (c *Connection) createDLOManifest(container string, objectName string, prefix string, contentType string) error {
	headers := make(Headers)
	headers["X-Object-Manifest"] = prefix
	manifest, err := c.ObjectCreate(container, objectName, false, "", contentType, headers)
	if err != nil {
		return err
	}

	if err := manifest.Close(); err != nil {
		return err
	}

	return nil
}

// Close satisfies the io.Closer interface
func (file *DynamicLargeObjectCreateFile) Close() error {
	return file.Flush()
}

func (file *DynamicLargeObjectCreateFile) Flush() error {
	err := file.conn.createDLOManifest(file.container, file.objectName, file.segmentContainer+"/"+file.prefix, file.contentType)
	if err != nil {
		return err
	}
	return file.conn.waitForSegmentsToShowUp(file.container, file.objectName, file.Size())
}

func (c *Connection) getAllDLOSegments(segmentContainer, segmentPath string) ([]Object, error) {
	//a simple container listing works 99.9% of the time
	segments, err := c.ObjectsAll(segmentContainer, &ObjectsOpts{Prefix: segmentPath})
	if err != nil {
		return nil, err
	}

	hasObjectName := make(map[string]struct{})
	for _, segment := range segments {
		hasObjectName[segment.Name] = struct{}{}
	}

	//The container listing might be outdated (i.e. not contain all existing
	//segment objects yet) because of temporary inconsistency (Swift is only
	//eventually consistent!). Check its completeness.
	segmentNumber := 0
	for {
		segmentNumber++
		segmentName := getSegment(segmentPath, segmentNumber)
		if _, seen := hasObjectName[segmentName]; seen {
			continue
		}

		//This segment is missing in the container listing. Use a more reliable
		//request to check its existence. (HEAD requests on segments are
		//guaranteed to return the correct metadata, except for the pathological
		//case of an outage of large parts of the Swift cluster or its network,
		//since every segment is only written once.)
		segment, _, err := c.Object(segmentContainer, segmentName)
		switch err {
		case nil:
			//found new segment -> add it in the correct position and keep
			//going, more might be missing
			if segmentNumber <= len(segments) {
				segments = append(segments[:segmentNumber], segments[segmentNumber-1:]...)
				segments[segmentNumber-1] = segment
			} else {
				segments = append(segments, segment)
			}
			continue
		case ObjectNotFound:
			//This segment is missing. Since we upload segments sequentially,
			//there won't be any more segments after it.
			return segments, nil
		default:
			return nil, err //unexpected error
		}
	}
}


# Translation of Odoo Server.
# This file contains the translation of the following modules:
# 	* hr_recruitment_survey
#
# Translators:
# Vasiliy Korobatov <korobatov@gmail.com>, 2019
# Martin Trigaux, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-10-07 07:12+0000\n"
"PO-Revision-Date: 2019-08-26 09:10+0000\n"
"Last-Translator: Martin Trigaux, 2019\n"
"Language-Team: Russian (https://www.transifex.com/odoo/teams/41243/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.hr_applicant_view_form_inherit
msgid ""
"Print\n"
"                        Interview"
msgstr ""
"Пчать\n"
"                        Интервью"

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.hr_applicant_view_form_inherit
msgid ""
"Start\n"
"                        Interview"
msgstr ""
"Начать\n"
"                        Интервью"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1
msgid "About you"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q7
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q7
msgid "Activities"
msgstr "Деятельность"

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.hr_applicant_view_form_inherit
msgid "Answer related job question"
msgstr "Ответить на вопрос, связанный с вакансией"

#. module: hr_recruitment_survey
#: model:ir.model,name:hr_recruitment_survey.model_hr_applicant
msgid "Applicant"
msgstr "Соискатель"

#. module: hr_recruitment_survey
#: model:ir.model.fields,field_description:hr_recruitment_survey.field_survey_survey__category
msgid "Category"
msgstr "Категория"

#. module: hr_recruitment_survey
#: model:ir.model.fields,help:hr_recruitment_survey.field_survey_survey__category
msgid ""
"Category is used to know in which context the survey is used. Various apps "
"may define their own categories when they use survey like jobs recruitment "
"or employee appraisal surveys."
msgstr ""

#. module: hr_recruitment_survey
#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_applicant__survey_id
#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_job__survey_id
msgid ""
"Choose an interview form for this job position and you will be able to "
"print/answer this interview from all applicants who apply for this job"
msgstr ""
"Выберите форму собеседования на эту должность, и вы сможете "
"распечатать/провести это собеседование со всеми соискателями, претендующими "
"на эту работу"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q3
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q3
msgid "Did you apply from an employee ?"
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.hr_job_survey_inherit
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.view_hr_job_kanban_inherit
msgid "Display Interview Form"
msgstr "Открыть схему собеседования"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q4
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q4
msgid "Education"
msgstr "Образование"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q2
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q2
msgid "From which university did or will you graduate ?"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row2
msgid "Getting on with colleagues"
msgstr "Ладить с коллегами"

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row8
msgid "Getting perks such as free parking, gym passes"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row1
msgid "Having a good pay"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row3
msgid "Having a nice office environment"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row7
msgid "Having freebies such as tea, coffee and stationery"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q1
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q2
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q3
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q4
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q5
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q6
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q7
#: model:survey.question,comments_message:hr_recruitment_survey.survey_recruitment_form_p1_q8
msgid "If other, please specify:"
msgstr "Если другое, укажите, пожалуйста:"

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_col2
msgid "Important"
msgstr "Важное"

#. module: hr_recruitment_survey
#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_job__survey_id
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.view_hr_job_kanban_inherit
msgid "Interview Form"
msgstr "Форма интервью"

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.res_config_settings_view_form
msgid "Interview Forms"
msgstr "Формы интервью"

#. module: hr_recruitment_survey
#: model:ir.model,name:hr_recruitment_survey.model_hr_job
msgid "Job Position"
msgstr "Должность"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q6
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q6
msgid "Knowledge"
msgstr "Знания"

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row6
msgid "Management quality"
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.view_hr_job_kanban_inherit
msgid "No Interview Form"
msgstr "Без плана собеседования"

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_col1
msgid "Not important"
msgstr "Неважно"

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row5
msgid "Office location"
msgstr "Расположение офиса"

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q5
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q5
msgid "Past work experiences"
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:survey.survey,description:hr_recruitment_survey.survey_recruitment_form
msgid ""
"Please answer those questions to help recruitment officers to preprocess "
"your application."
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:survey.question,description:hr_recruitment_survey.survey_recruitment_form_p1
msgid ""
"Please fill information about you: who you are, what are your education, experience, and activities.\n"
"    It will help us managing your application."
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:survey.question,description:hr_recruitment_survey.survey_recruitment_form_p1_q4
#: model_terms:survey.question,description:hr_recruitment_survey.survey_recruitment_form_p1_q5
msgid ""
"Please summarize your education history: schools, location, diplomas, ..."
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:survey.question,description:hr_recruitment_survey.survey_recruitment_form_p1_q7
msgid ""
"Please tell us a bit more about yourself: what are your main activities, ..."
msgstr ""

#. module: hr_recruitment_survey
#: model_terms:ir.ui.view,arch_db:hr_recruitment_survey.hr_applicant_view_form_inherit
msgid "Print interview report"
msgstr "Печать отчета собеседования"

#. module: hr_recruitment_survey
#: model:ir.model.fields.selection,name:hr_recruitment_survey.selection__survey_survey__category__hr_recruitment
msgid "Recruitment"
msgstr "Найм"

#. module: hr_recruitment_survey
#: model:survey.survey,title:hr_recruitment_survey.survey_recruitment_form
msgid "Recruitment Form"
msgstr "Рекрутинговая форма"

#. module: hr_recruitment_survey
#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant__response_id
msgid "Response"
msgstr "Ответ"

#. module: hr_recruitment_survey
#: model:ir.model,name:hr_recruitment_survey.model_survey_survey
#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant__survey_id
msgid "Survey"
msgstr "Опрос"

#. module: hr_recruitment_survey
#: model_terms:survey.survey,thank_you_message:hr_recruitment_survey.survey_recruitment_form
msgid "Thank you for answering this survey. We will come back to you soon."
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q1
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q2
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q3
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q4
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q5
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q6
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q7
#: model:survey.question,validation_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q8
msgid "The answer you entered is not valid."
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q1
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q2
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q3
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q4
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q5
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q6
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q7
#: model:survey.question,constr_error_msg:hr_recruitment_survey.survey_recruitment_form_p1_q8
msgid "This question requires an answer."
msgstr "Этот вопрос требует ответа."

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_col3
msgid "Very important"
msgstr "Очень важно"

#. module: hr_recruitment_survey
#: model_terms:survey.question,description:hr_recruitment_survey.survey_recruitment_form_p1_q6
msgid "What are your main knowledge regarding the job you are applying to ?"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q8
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q8
msgid "What is important for you ?"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.question,question:hr_recruitment_survey.survey_recruitment_form_p1_q1
#: model:survey.question,title:hr_recruitment_survey.survey_recruitment_form_p1_q1
msgid "Which country are you from ?"
msgstr ""

#. module: hr_recruitment_survey
#: model:survey.label,value:hr_recruitment_survey.survey_recruitment_form_p1_q8_row4
msgid "Working with state of the art technology"
msgstr ""


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>QmitkMicronTrackerWidget</class>
 <widget class="QWidget" name="QmitkMicronTrackerWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>321</width>
    <height>181</height>
   </rect>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_11">
   <item>
    <widget class="QLabel" name="microntracker_label">
     <property name="text">
      <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<meta name="qrichtext" content="1" />

MicronTracker
</string>
     </property>
    </widget>
   </item>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout_13">
     <item>
      <layout class="QVBoxLayout" name="verticalLayout_10">
       <item>
        <widget class="QLabel" name="m_MTCalibrationFile">
         <property name="text">
          <string>Calibration File: <none></string>
         </property>
        </widget>
       </item>
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_16">
         <item>
          <widget class="QPushButton" name="m_SetMTCalibrationFile">
           <property name="text">
            <string>Set Calibration File</string>
           </property>
          </widget>
         </item>
         <item>
          <spacer name="horizontalSpacer_5">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
            </size>
           </property>
          </spacer>
         </item>
        </layout>
       </item>
       <item>
        <spacer name="horizontalSpacer_10">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>40</width>
           <height>20</height>
          </size>
         </property>
        </spacer>
       </item>
       <item>
        <spacer name="verticalSpacer_4">
         <property name="orientation">
          <enum>Qt::Vertical</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>20</width>
           <height>40</height>
          </size>
         </property>
        </spacer>
       </item>
      </layout>
     </item>
     <item>
      <layout class="QVBoxLayout" name="verticalLayout_9">
       <item>
        <widget class="QTextEdit" name="m_outputTextMicronTracker">
         <property name="minimumSize">
          <size>
           <width>120</width>
           <height>50</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>120</width>
           <height>80</height>
          </size>
         </property>
         <property name="baseSize">
          <size>
           <width>120</width>
           <height>0</height>
          </size>
         </property>
         <property name="html">
          <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<meta name="qrichtext" content="1" />

output:
</string>
         </property>
         <property name="textInteractionFlags">
          <set>Qt::NoTextInteraction</set>
         </property>
        </widget>
       </item>
       <item>
        <widget class="QPushButton" name="m_testConnectionMicronTracker">
         <property name="minimumSize">
          <size>
           <width>120</width>
           <height>0</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>120</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="baseSize">
          <size>
           <width>120</width>
           <height>0</height>
          </size>
         </property>
         <property name="text">
          <string>test connection</string>
         </property>
        </widget>
       </item>
      </layout>
     </item>
    </layout>
   </item>
   <item>
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>40</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


math.cos(query.life_time * 343.774) * 1.6 - this

math.cos(query.life_time * 1489.6) * -45.0

math.cos(query.life_time * 1489.6) * -22.0

math.cos(query.life_time * 1489.6) * 45.0

math.cos(query.life_time * 1489.6) * 22.0


# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Nebula, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import logging

from horizon import tabs

from .tabs import SystemInfoTabs

LOG = logging.getLogger(__name__)

class IndexView(tabs.TabbedTableView):
    tab_group_class = SystemInfoTabs
    template_name = 'admin/info/index.html'


/**
 * Copyright 2016-present, Baifendian, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

@import '../variables.less';

@duration: .2s;
@zIndex: 1000;

.bfd-modal--scrollbar-measure {
  position: absolute;
  top: -9999px;
  width: 50px;
  height: 50px;
  overflow: scroll;
}

body.bfd-modal--open {
  overflow: hidden;
}

.bfd-modal {
  display: none;
  backface-visibility: hidden;
}

.bfd-modal__backdrop {
  position: fixed;
  top: 0;
  right: 0;
  bottom: -1px;
  left: 0;
  opacity: 0;
  transition: all @duration;
  z-index: @zIndex;
  background-color: rgba(0, 0, 0, .8);
}

.bfd-modal__modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: @zIndex;
  -webkit-overflow-scrolling: touch;
  outline: 0;
  overflow-x: hidden;
  overflow-y: auto;

}

.bfd-modal__modal-dialog {
  margin: 100px auto;
  width: 600px;
  transition: all @duration;
}

.bfd-modal__modal-dialog--lock {
  animation: bfd-modal-shake .8s;
}

@keyframes bfd-modal-shake {
  10%, 90% {
    transform: translate3d(-1px, 0, 0);
  }

  20%, 80% {
    transform: translate3d(2px, 0, 0);
  }

  30%, 50%, 70% {
    transform: translate3d(-4px, 0, 0);
  }

  40%, 60% {
    transform: translate3d(4px, 0, 0);
  }
}

.bfd-modal__modal-content {
  opacity: 0;
  transform: scale(.98) translate3d(0, -10%, 0);
  transform-origin: top;
  transition: all @duration;
}

.bfd-modal--sm {
  .bfd-modal__modal-dialog {
    width: 300px;
  }
}

.bfd-modal--lg {
  .bfd-modal__modal-dialog {
    width: 1000px;
  }
}

.bfd-modal__modal-header {
  background-color: @primary-color-deep;
  color: #fff;
  padding: 15px 20px;
  position: relative;
  border-top-left-radius: 2px;
  border-top-right-radius: 2px;
  h1, h2, h3, h4, h5, h6 {
    margin: 0;
    padding: 0;
    font-weight: normal;
    font-size: 14px;
  }
}

.bfd-modal__modal-header-close {
  position: absolute;
  top: 50%;
  right: 15px;
  margin-top: -11px;
}

.bfd-modal__modal-body {
  border-bottom-left-radius: 2px;
  border-bottom-right-radius: 2px;
  padding: 20px;
  background-color: #fff;
}

div.bfd-modal--open {
  .bfd-modal__backdrop {
    opacity: .6;
  }
  .bfd-modal__modal-content {
    opacity: 1;
    transform: scale(1) translate3d(0, 0, 0);
  }
}


.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
}

.App-header {
  background-color: #222;
  height: 150px;
  padding: 20px;
  color: white;
}

.App-intro {
  font-size: large;
}

@keyframes App-logo-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}


================================
Example: Microsoft Windows image
================================

This example creates a Windows Server 2012 qcow2 image,
using the :command:`virt-install` command and the KVM hypervisor.

#. Follow these steps to prepare the installation:

   #. Download a Windows Server 2012 installation ISO.
      Evaluation images are available on the `Microsoft website
      <http://www.microsoft.com/en-us/evalcenter/
      evaluate-windows-server-2012>`_ (registration required).
   #. Download the signed VirtIO drivers ISO from the `Fedora website
      <https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html>`_.
   #. Create a 15 GB qcow2 image:

      .. code-block:: console

         $ qemu-img create -f qcow2 ws2012.qcow2 15G

#. Start the Windows Server 2012 installation with the
   :command:`virt-install` command:

   .. code-block:: console

      # virt-install --connect qemu:///system \
        --name ws2012 --ram 2048 --vcpus 2 \
        --network network=default,model=virtio \
        --disk path=ws2012.qcow2,format=qcow2,device=disk,bus=virtio \
        --cdrom /path/to/en_windows_server_2012_x64_dvd.iso \
        --disk path=/path/to/virtio-win-0.1-XX.iso,device=cdrom \
        --vnc --os-type windows --os-variant win2k12 \
        --os-distro windows --os-version 2012

   Use :command:`virt-manager` or :command:`virt-viewer` to
   connect to the VM and start the Windows installation.

#. Enable the VirtIO drivers. By default, the Windows installer does not detect
   the disk.

#. Load VirtIO SCSI drivers and  network drivers by choosing an installation
   target when prompted. Click :guilabel:`Load driver` and browse the file
   system.

#. Select the ``E:\virtio-win-0.1XX\viostor\2k12\amd64`` folder. The Windows
   installer displays a list of drivers to install.

#. Select the VirtIO SCSI drivers.

#. Click :guilabel:`Load driver` and browse the file system, and
   select the ``E:\NETKVM\2k12\amd64`` folder.

#. Select the network drivers, and continue the installation. Once the
   installation is completed, the VM restarts.

#. Define a password for the administrator when prompted.

#. Log in as administrator and start a command window.

#. Complete the VirtIO drivers installation by running the
   following command:

   .. code-block:: console

      C:\pnputil -i -a E:\virtio-win-0.1XX\viostor\2k12\amd64\*.INF

#. To allow the :term:`Cloudbase-Init` to run scripts during an instance
   boot, set the PowerShell execution policy to be unrestricted:

   .. code-block:: console

      C:\powershell
      C:\Set-ExecutionPolicy Unrestricted

#. Download and install the ``Cloudbase-Init``:

   .. code-block:: console

      C:\Invoke-WebRequest -UseBasicParsing https://cloudbase.it/downloads/CloudbaseInitSetup_Stable_x64.msi -OutFile cloudbaseinit.msi
      C:\.\cloudbaseinit.msi

   In the :guilabel:`configuration options` window,
   change the following settings:

   * Username: ``Administrator``
   * Network adapter to configure: ``Red Hat VirtIO Ethernet Adapter``
   * Serial port for logging: ``COM1``

   When the installation is done, in the
   :guilabel:`Complete the Cloudbase-Init Setup Wizard` window,
   select the :guilabel:`Run Sysprep` and :guilabel:`Shutdown`
   check boxes and click :guilabel:`Finish`.

   Wait for the machine shutdown.

Your image is ready to upload to the Image service:

.. code-block:: console

   $ openstack image create --disk-format qcow2 --file ws2012.qcow2 WS2012


/**
 *
 * WARNING! This file was autogenerated by:
 *  _   _ _   _ __   __
 * | | | | | | |\ \ / /
 * | | | | |_| | \ V /
 * | | | |  _  | /   \
 * | |_| | | | |/ /^\ \
 *  \___/\_| |_/\/   \/
 *
 * This file was autogenerated by UnrealHxGenerator using UHT definitions.
 * It only includes UPROPERTYs and UFUNCTIONs. Do not modify it!
 * In order to add more definitions, create or edit a type with the same name/package, but with an `_Extra` suffix
**/
package unreal.mediaplayereditor;

/**
  WARNING: This type was not defined as DLL export on its declaration. Because of that, some of its methods are inaccessible

  Implements a factory for UFileMediaSource objects.
**/
@:umodule("MediaPlayerEditor")
@:glueCppIncludes("Private/Factories/FileMediaSourceFactoryNew.h")
@:noClass @:uextern @:uclass extern class UFileMediaSourceFactoryNew extends unreal.editor.UFactory {

}