コード例 #1
0
    def __call__(self, parser, namespace, values, option_string=None):

        _eases, _shapes = argutils.easers
        ease = shape = t0 = t1 = ''
        items = []

        if values:
            items = [i.split('=') for i in values.split(',')]
            valid = [len(x) == 2 for x in items]
            e = "unrecognized merge format: {}".format(values)
            assert all(valid), ToolError(e, parser.print_help)

        for key, value in items:

            if key == 't0':
                t0 = params.animation.times.type_t0(value)
            elif key == 't1':
                t1 = params.animation.times.type_t0(value)
            elif key == 'ease':
                ease = argutils.choice(value, _eases, 'ease')
            elif key == 'shape':
                shape = argutils.choice(value, _shapes, 'shape')
            else:
                e = "unknown merge option/argument: {}={}".format(key, value)
                raise ToolError(e, parser.print_help)

        setattr(namespace, self.dest, (t0, t1, ease, shape))
コード例 #2
0
    def choice(self, obj, choices, arg=None, convert=str):
        """checks if a object is in a container of available choices

        emulates argparse 'choices' function

        :param obj: `object`, object to check
        :param choices: `iter`, container of available choices
        :param arg: `str`, argument used for the call
        :param convert: `type`, convert object to specified type
        :return: `obj` if `obj` is in choices
        :raise: `ToolError` if `obj` not in `choices` or `convert` fails
        """

        choices = [str(x) for x in choices]
        arg = self._arg(arg)
        e = ("{arg}: invalid choice: {obj} (choose from {choices})".format(
            arg=arg, obj=obj, choices=', '.join(choices)))

        if str(obj) in choices:
            try:
                return convert(obj)
            except ValueError:
                raise ToolError(e, self.print_help)

        raise ToolError(e, self.print_help)
コード例 #3
0
    def search(self, paths, schema_file=None, msg=None):
        """searches for valid json files from a list of files or directories

        :param paths: `str`/`iter`, files/directories to search in; if `str`,,
                      the object is auto converted to a list
        :param schema_file: `str`, path to json schema file (for validation)
        :param msg: `str`, override default status message
        :yields: available json files
        :raise: `ToolError` if an object in `paths` is invalid
        """

        paths = utils.make_iter(paths)

        for i, path_in in enumerate(paths, start=1):
            path = utils.full_path(path_in)

            is_file_or_dir = os.path.isdir(path) or os.path.isfile(path)
            e = "not a valid file or directory : " + path_in
            assert is_file_or_dir, ToolError(e, self.print_help)

            msg = msg or "checking for json content"
            msgutils.status(msg, src=path, count=i)

            if os.path.isfile(path):
                if self.data(path, schema_file):
                    yield path

            elif os.path.isdir(path):
                file_paths = utils.walk_path(path)

                for path_ in file_paths:
                    if self.data(path_, schema_file):
                        yield path_
コード例 #4
0
ファイル: tool.py プロジェクト: meghadri/lytro-power-tools
    def search_raw(self, paths):
        """searches for RAW file types from a list of files or directories

        :param paths: `str`/`iter`, files/directories to search in; if `str`,,
                      the object is auto converted to a list
        :yield: applicable RAW files
        :raise: `ToolError` if invalid file or directory specified
        """

        paths = utils.make_iter(paths)

        def valid(p):
            return re.match(self.raw_pattern, p)

        for i, path in enumerate(paths, start=1):
            path = utils.full_path(path)

            is_file_or_dir = os.path.isdir(path) or os.path.isfile(path)
            e = "not a valid file or directory : " + path
            assert is_file_or_dir, ToolError(e, self.print_help)

            msg = "checking for RAW image data"
            msgutils.status(msg, src=path, count=i)

            if os.path.isfile(path) and valid(path):
                yield path

            elif os.path.isdir(path):
                file_paths = utils.walk_path(path, pattern=self.raw_pattern)

                for file_path in file_paths:
                    yield file_path
コード例 #5
0
    def __call__(self, data=None, recipe_file=None, animate=False):
        """:raise: `ToolError` if invalid view parameter is found in data"""

        _data = {}
        if recipe_file:
            _data.update(jsonutils.data(recipe_file))
        if data:
            _data.update(data)

        for param, value in _data.items():

            if param in self._unsupported:
                self.unsupported_data[param] = value
                continue

            name = key_cls(param)
            e = "invalid parameter: " + param
            assert hasattr(self, name), ToolError(e, print_help_obj)

            cls = getattr(self, name)

            if animate:
                if not cls.animation:
                    continue
                cls = cls.anim

            cls(value)
コード例 #6
0
    def all_or_none(self, allow_none=True, index=None, **kwargs):
        """requires all kwargs have values

        :param kwargs: keyword args parsed through for values
        :param allow_none: `bool`,, allows all kwargs to not have value
        :param index: `int`, indicates that kwargs are a subset of an array and
                      changes the assertion error to include an index number
        :return: dict object of kwargs if values present, empty dict if not
        :raise: `ToolError` specified `kwargs` that both do/don't have values
        """
        def arg_str(l):
            return ', '.join([self._arg(x) for x in l])

        values = kwargs.values()
        any_ = utils.any_(values, iter_=False)
        all_ = utils.all_(values, iter_=False)

        set_args = [k for k, v in kwargs.items() if v]
        not_set_args = [k for k, v in kwargs.items() if not v]

        req = [k for k in set_args if k not in not_set_args]
        req_args = kwargs if set_args else {}

        must = not (any_ and not all_) if allow_none else all_

        e = ("{set_}: requires additional arguments; "
             "{not_} not set".format(set_=arg_str(req),
                                     not_=arg_str(not_set_args)))

        if index:
            e = "index {}: ".format(index) + e

        assert must, ToolError(e, self.print_help)
        return req_args
コード例 #7
0
    def in_range(self, obj, arg=None, range_=(0, 0), type_=int, clip=True):
        """verifies if a number is in range of the specified range

        :param obj: `int`/`float`, object to check
        :param arg: `str`, argument used for the call
        :param range_: `tuple`, range to check if object is in
        :param type_: `int`/`float`, expected type
        :param clip: `bool`, adjust value to be within requested range
        :return: ``self.number(obj)`` if number in range
        :raise: `ToolError` if `obj` not in range
        """

        min_, max_ = range_
        num = self.number(obj, arg=arg, type_=type_)
        num = int(round(num)) if type_ is int else num
        arg = self._arg(arg)
        lt_gt = self.lt_gt(num, min_, max_)

        if not clip:
            e = self.bad_range.format(obj=obj, arg=arg, min_=min_, max_=max_)
            assert lt_gt is not False, ToolError(e, self.print_help)

        if lt_gt is False:
            max_closer = (num - min_) > abs(num - max_)
            num = max_ if max_closer else min_

        return num
コード例 #8
0
    def cmd_picture_put(self, args):
        """put (update) user picture information

        :param args: `argparse.Namespace`, input args from Web Tool argparse
        :raise: `ToolError` if specified picture ID failed to ``GET``
        """

        self._set_print_help(args)
        msgutils.msg("updating information for picture {}".format(
            args.picture_id))

        before = self._match_album_picture(self.username, args.picture_id)

        e = "could not perform lookup for picture {}".format(args.picture_id)
        assert before, ToolError(e, self.print_help)

        msgutils.msg("before:")
        msgutils.dumps(before)

        album_id = before['album_id']

        self.put_picture(album_id=album_id,
                         picture_id=args.picture_id,
                         caption=args.caption)

        after = self.get_picture(album_id=album_id, picture_id=args.picture_id)
        msgutils.msg("after:")
        msgutils.dumps(after)
コード例 #9
0
    def search(self, paths):
        """search a file or directory for recipe files

        :param paths:  `list`, list of files or directories to search
        :yield: valid recipe files
        :raise: `ToolError` if a specified path is invalid
        """

        paths = utils.make_iter(paths)
        msg = "searching for valid v{} recipe files".format(self._version)
        isdir = os.path.isdir
        isfile = os.path.isfile

        for i, path in enumerate(paths, start=1):

            msgutils.status(msg, src=path, count=i)
            path = os.path.expanduser(path)

            e = "not a valid file or directory : " + path
            assert (isdir(path) or isfile(path)), ToolError(e, self.print_help)

            if os.path.isfile(path) and self.verify(path):
                yield os.path.abspath(path)

            elif os.path.isdir(path):
                file_paths = utils.walk_path(path, ext='json')

                for file_path in file_paths:
                    if self.verify(file_path):
                        yield os.path.abspath(file_path)
コード例 #10
0
    def error(self, message):
        """
        overrides error function provided by argparse
        :param message: message to display when error occurs
        :raise: `ToolError` if error occurs
        """

        raise ToolError(message, self.print_help)
コード例 #11
0
    def _assert_points(self, points, param):
        """checks if a animation line contains enough data for a given task

        :raise: `ToolError` if no or bad amount of animation data points found
        """

        e = param + ": missing animation data"
        assert points, ToolError(e, self.print_help)
コード例 #12
0
    def _assert_response(self, resp, code=200):
        """:raise: `ToolError` (w/ web msg) if unexpected web response code"""

        e = 'HTTP {} - {}'.format(resp['code'], resp['msg'])

        if 'data' in resp and 'message' in resp['data']:
            e = resp['data']['message']

        assert resp['code'] == code, ToolError(e, self.print_help)
コード例 #13
0
    def append(self,
               param,
               time=None,
               value=None,
               dt1=None,
               dv1=None,
               t0=None,
               v0=None,
               view=None,
               initial_value=None,
               default_value=None):
        """given available parameters, determine the next best value to append

        :param param: `str`, animation parameter to perform function on
        :param time: `float`, moment in time to apply value
        :param value: `float`/`int`, parameter value to apply
        :param dt1: `list`, succeeding time handle pair values
        :param dv1: `list`, succeeding value handle pair values
        :param t0: `int`/`float`, start time, in seconds
        :param v0: `int`/`float`, start value
        :param view: the recipe's view parameter value for the corresponding
                     animation parameter
        :param initial_value: the starting value of the animation parameter
        :param default_value: the default value of the parameter defined in
                              the LFP schema
        :return: best guessed t0/v0 values
        :raise: `ToolError` if no appropriate start value found
        """

        if not any_(t0):

            t0 = self._auto_buffer

            if any_(dt1) and any_(time):
                t0 += time - dt1
            elif any_(time):
                t0 += time

        if not any_(v0):

            if any_(dv1) and any_(value):
                v0 = value - dv1
            elif any_(value):
                v0 = value
            elif any_(initial_value):
                v0 = initial_value
            elif any_(view):
                v0 = view
            elif any_(default_value):
                v0 = default_value
            else:
                e = param + ": no starting value found; specify --v0"
                ToolError(e, self.print_help)

        return t0, v0
コード例 #14
0
ファイル: tool.py プロジェクト: meghadri/lytro-power-tools
    def verify_image_paths(self, lfp_path, image_paths):
        """verifies all images referenced in an unpacked LFP are present

        :param lfp_path: `str`, lfp_path being checked
        :param image_paths: `list`, absolute paths to images
        :raise: `ToolError` if any LFP image file is missing
        """

        for path in image_paths:
            e = "missing {} to pack LFP file {}".format(path, lfp_path)
            assert os.path.isfile(path), ToolError(e, self.print_help)
コード例 #15
0
ファイル: webtool.py プロジェクト: meghadri/lytro-power-tools
    def extant_file_type(path):
        """`argparse` type: checks if path exists on the file system

        :param path: path to check
        :return: path if exists
        :raise: `ToolError` if file does not exist
        """

        err = "file does not exist: {}".format(path)
        assert os.path.exists(path), ToolError(err, parser.print_help)
        return path
コード例 #16
0
    def __init__(self, path, print_help=object, store_raw=False):

        self.print_help = self.set_print_help(print_help)
        self.path = path
        self._store_raw = store_raw
        self.file_size = os.path.getsize(path)

        try:
            self.blobs = self._get_blobs
        except Exception as e:
            raise ToolError(e, self.print_help)
        else:
            e = "not a valid LFP file : " + self.path
            assert self.blobs, ToolError(e, self.print_help)

        self._master = {}
        self._ref_md = {}
        self.picture = {}
        self.private = []
        self.public = []
        self.master = self._get_master
コード例 #17
0
    def _assert_src(self, src, paths, cmd, raw_in=False, range_=(0, 0)):
        """:raise: `ToolError`, if no valid LFPs found for current command"""

        s = 'RAW' if raw_in else 'LFP'
        e = cmd + ": no valid {} files found".format(s)

        if range_[1]:
            a, b = range_
            e += " with range: {} - {}".format(a, b)

        e += ": " + ','.join(paths)
        assert src, ToolError(e, self.print_help)
コード例 #18
0
ファイル: webtool.py プロジェクト: meghadri/lytro-power-tools
    def album_description_type(desc):
        """`argparse` type: checks if the album description is <= 3000 chars

        :param desc: `str`, to check
        :return: album description  if appropriate length
        :raise: `ToolError` if description longer than 3000 chars
        """

        err = ("album description too long (length: {}, max: 3000): \"{}\"".
               format(len(desc), desc))
        assert len(desc) <= 3000, ToolError(err, parser.print_help)
        return desc
コード例 #19
0
ファイル: webtool.py プロジェクト: meghadri/lytro-power-tools
    def album_name_type(name):
        """`argparse` type: checks if the album name is <= 140 chars

        :param name: `str`, to check
        :return: album if appropriate length
        :raise: `ToolError` if name longer than 140 chars
        """

        err = ("album name too long (length: {}, max: 140): \"{}\"".format(
            len(name), name))
        assert len(name) <= 140, ToolError(err, parser.print_help)
        return name
コード例 #20
0
ファイル: utils.py プロジェクト: meghadri/lytro-power-tools
    def mkdir(self, dir_path):
        """make a directory

        :param dir_path: `str`, input directory to create
        :raise: `ToolError` if there is an `OSError` exception
        """

        try:
            os.makedirs(dir_path)
            return dir_path
        except OSError as e:
            raise ToolError(e, self.print_help)
コード例 #21
0
    def _rep_sanity(self, action, rep, rep_type, options):
        """checks imagerep/depthrep compatibility with the chosen action

        :raise: `ToolError` if representation not in available options
        """

        arg = '--' + action.replace('_', '-')
        opt = ', '.join(options)

        e = ("{}: invalid {} choice: {} (choose from {})".format(
            arg, rep_type, rep, opt))

        assert rep in options, ToolError(e, self.print_help)
コード例 #22
0
    def flush(self):
        """validates loaded recipe and writes recipe file to disk

        :raise: `ToolError` if `self.path` is not set"""

        self.dependencies()
        self.validate()
        self.zulu_time()
        e = "recipe output file not set"
        assert self.path, ToolError(e, print_help_obj)
        store = self.store
        store.update(self.unsupported_data)
        utils.write(self.path, od(sorted(store.items())))
コード例 #23
0
    def _assert_t0_lt_t1(self, t0, t1, param=''):
        """checks if t0 value is less than t1 value

        :raise: `ToolError` if t0 greater than t1
        """

        param = "{}: ".format(param) if param else ""

        if any_(t1):
            t0 = t0 if any_(t0) else self._auto_buffer
            e = param + "t0/t1 duration is less than .5 seconds; "
            e += "t0={}, t1={}".format(t0, t1)
            assert t0 + .5 < t1, ToolError(e, self.print_help)
コード例 #24
0
    def assert_len(self, props, len_=1):
        """assert that values in a dictionary are of an acceptable length

        :param props: `dict`, dictionary to parse through
        :param len_: acceptable length of dictionary values
        :raise: `ToolError` if `len_` does not match length of `props`
        """

        for key, value in props.items():
            arg = self._arg(key)
            e = arg + ": only {} value can be specified".format(len_)
            l = len(value) if hasattr(value, '__len__') else 1
            assert l == len_, ToolError(e, self.print_help)
コード例 #25
0
    def json_file(self, file_path_in):
        """verifies that a inputted file is a valid JSON file

        :param file_path_in: `str`, input path to check
        :return: file path if valid
        :raise: `ToolError` if `file_path_in` does not contain JSON data
        """

        file_path = utils.full_path(file_path_in)
        json_data = jsonutils.data(file_path)
        e = "invalid JSON file: " + file_path_in
        assert json_data or json_data == {}, ToolError(e, self.print_help)
        return file_path
コード例 #26
0
ファイル: webtool.py プロジェクト: meghadri/lytro-power-tools
    def picture_caption_type(caption):
        """`argparse` type: checks if the picture caption is <= 140 chars

        :param caption: `str`, to check
        :return: picture caption if appropriate length
        :raise: `ToolError` if caption longer than 140 chars
        """

        err = (
            "picture caption too long (length: {}, max: 140): \"{}\"".format(
                len(caption), caption))

        assert len(caption) <= 140, ToolError(err, parser.print_help)
        return caption
コード例 #27
0
    def __call__(self, *args, **kwargs):
        """:raise: `ToolError` if `args[0]` not a valid control point format"""

        values = args[0]
        if isinstance(values, dict):
            x = values['x']
            y = values['y']
        elif isinstance(values, tuple):
            x, y = values
        else:
            e = "invalid control point format: " + str(values)
            raise ToolError(e, print_help_obj)

        self.x(x)
        self.y(y)
コード例 #28
0
    def boolean(self, obj, arg=None):
        """checks if object is boolean

        :param obj: `object`, object to check
        :param arg: `str`, argument used for the call
        :return: `obj` if bool
        :raise: `ToolError` if `obj` not boolean
        """

        if isinstance(obj, bool):
            return obj

        arg = self._arg(arg)
        e = "{}: expected boolean value: {}".format(arg, obj)
        raise ToolError(e, self.print_help)
コード例 #29
0
    def zulu_time(self, str_, arg=None):
        """verifies that the inputted string matches zulu time format

        :param str_: `type`, object to check
        :param arg: `str`, argument used for the call
        :return: string version of object
        :raise: `ToolError` if `str_` not zulu time key format
        """

        try:
            _ = datetime.datetime.strptime(str_, '%Y-%m-%dT%H:%M:%S.%fZ')
            return str_
        except Exception as e:
            arg = self._arg(arg)
            e = "{arg}: {e}".format(arg=arg, e=e)
            raise ToolError(e, self.print_help)
コード例 #30
0
    def unsigned_number(self, obj, arg=None):
        """verifies if an object is an unsigned int or float

        :param obj: `int`/`float`, object to check
        :param arg: `str`, argument used for the call
        :return: ``self.number(obj)`` if unsigned
        :raise: `ToolError` if number is not unsigned
        """

        num = self.number(obj, arg=arg)
        if num >= 0:
            return num

        arg = self._arg(arg)
        e = self.bad_range.format(arg=arg, obj=obj, min_=0, max_='..')
        raise ToolError(e, self.print_help)