Giter Site home page Giter Site logo

vs-tools's Introduction

vs-tools

Functions and utils related to VapourSynth


This module is a collection of functions, utils, types, type-utils, and more aimed at helping at having a common ground between VapourSynth packages, and simplify writing them.

For support you can check out the JET Discord server.

How to install

Install vstools with the following command:

pip install vstools

Or if you want the latest git version, install it with this command:

pip install git+https://github.com/Jaded-Encoding-Thaumaturgy/vs-tools.git

vs-tools's People

Contributors

dependabot[bot] avatar ichunjo avatar justintarthur avatar lightarrowsexe avatar ozanderr avatar setsugennoao avatar shssoichiro avatar vodes avatar wiwaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

vs-tools's Issues

Timecodes.assume_vfr error and warning

When using Timecodes.assume_vfr, it returns the following error:

ValueError: (replace_ranges) RFS: Clip frame rates don't match, enable mismatch if you want variable format.

Setting it to mismatch=True seems to still not display it as VFR in vspreview.

image

replace_ranges also throws a warning:

C:\Program Files\Python311\Lib\site-packages\vstools\utils\ranges.py:168: UserWarning: replace_ranges: use_plugin is deprecated!
  warnings.warn('replace_ranges: use_plugin is deprecated!')

Determine exceptions `func` automatically

Talked about this in PMs. There are ways to automatically determine the caller function, so it might be a good idea to implement that so people don't need to worry about it (but they're still able to override it should they want to).

Below is example code from a private module I'm currently working on, which might be reusable here (and can likely be improved upon further, like returning the ClassName.method if the caller originates from a class?):

import inspect

def get_caller_function() -> str | None:
    """Attempt to call the caller function. This is used for exception handling."""
    for f in inspect.stack()[1:]:
        func = f.function
        func_origin = Path(f.filename).name

        # Check if private function/method
        if func.startswith("_"):
            continue

        # Check if it's an exception or error class.
        if any(x in func for x in ["Exception", "Error"]):
            continue

        # Check if it originates from an `exceptions.py` or `errors.py` file.
        if any(x in func_origin.lower() for x in ["exceptions.py", "error.py"]):
            continue

        # Finally, return the function name.
        return func

And a basic example of how I implemented it in my module:

from vstools import CustomError, SupportsString, FuncExceptT
from typing import Any

class BaseCustomError(CustomError):
    def __init__(self,
        message: SupportsString | None = None,
        reason: SupportsString | None = None,
        func: FuncExceptT | None = None,
        **kwargs: Any
    ) -> None:
        func = func or get_caller_function()

        if message:
            message = str(message)

        return super().__init__(message, func, reason, **kwargs)

As mentioned, I'm sure this can be improved upon a lot, but hopefully this serves as a nice jumping-off point.

`Keyframes.to_file` create dir if it doesn't exist

It'd be nice if a directory would be automatically created if it didn't exist.

2023-02-17 18:51:33.464: root: ERROR: [Errno 2] No such file or directory: 'E:\\Anime\\Fansubbing\\Git Repositories\\Encoding Projects\\[Kaleido-subs]\\Work in Progress\\Negima! Series [DVD]_hidden\\S2\\_assets\\NegimaS2DVD_01_scening.txt'
2023-02-17 18:51:33.468: root: ERROR: Traceback (most recent call last):
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vsengine\vpy.py", line 219, in _execute
    runpy.run_path(str(script), module.__dict__, module.__name__)
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 291, in run_path
    return _run_module_code(code, init_globals, run_name,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 98, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vspreview\core\vsenv.py", line 19, in _monkey_runpy_func
    glob_dict = orig_runpy_run_code(*args, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 88, in _run_code
    exec(code, run_globals)
  File "E:\Anime\Fansubbing\Git Repositories\Encoding Projects\[Kaleido-subs]\Work in Progress\Negima! Series [DVD]_hidden\S2\NegimaS2DVD_01.py", line 323, in <module>
    PREFILTER = prefilter(SRC.clip_cut)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\Anime\Fansubbing\Git Repositories\Encoding Projects\[Kaleido-subs]\Work in Progress\Negima! Series [DVD]_hidden\S2\NegimaS2DVD_01.py", line 46, in prefilter
    Keyframes.from_clip(BD.clip_cut).to_file(scening_path)
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\functions\timecodes.py", line 317, in to_file
    out_path.touch()
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\pathlib.py", line 1108, in touch
    fd = os.open(self, flags, mode)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'E:\\Anime\\Fansubbing\\Git Repositories\\Encoding Projects\\[Kaleido-subs]\\Work in Progress\\Negima! Series [DVD]_hidden\\S2\\_assets\\NegimaS2DVD_01_scening.txt'

`insert_clip` Show total frame lengths in exception

The current exception thrown when a "clip is too long" isn't always really helpful. It'd be neat if it told the user by how many frames it was too long. This way the user could easily see whether they slightly miscalculated the trim, or if they accidentally passed the wrong clip because the length is obviously wrong.

Additionally, maybe a parameter to allow the user to pass a clip and have it simply trim it by the end if it exceeds the processed clip's length might be nice.

LengthMismatchError does not display lengths as reason

(also, typo: "lenghts" -> "lengths")
image

2023-02-15 21:59:52.443: root: ERROR: (diff) All the lenghts must be equal! ()
2023-02-15 21:59:52.450: root: ERROR: Traceback (most recent call last):
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vsengine\vpy.py", line 219, in _execute
    runpy.run_path(str(script), module.__dict__, module.__name__)
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 291, in run_path
    return _run_module_code(code, init_globals, run_name,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 98, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vspreview\core\vsenv.py", line 19, in _monkey_runpy_func
    glob_dict = orig_runpy_run_code(*args, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 88, in _run_code
    exec(code, run_globals)
  File "E:\Anime\Fansubbing\Git Repositories\Encoding Projects\[Kaleido-subs]\Work in Progress\Joshiraku [BD]_new_hidden\JoshirakuBD_07.py", line 75, in <module>
    FILTERED = filterchain(SRC.clip_cut, NCOP.clip_cut, NCED.clip_cut, OP_03.clip_cut)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\Anime\Fansubbing\Git Repositories\Encoding Projects\[Kaleido-subs]\Work in Progress\Joshiraku [BD]_new_hidden\JoshirakuBD_07.py", line 44, in filterchain
    lvf.diff(o_u, p_u, thr=80).std.SetFrameProps(Name="diff on U plane")
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\lvsfunc\comparison.py", line 625, in diff
    LengthMismatchError.check(diff, a.num_frames, b.num_frames)
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\exceptions\generic.py", line 182, in check
    raise cls(func, items, **kwargs)
LengthMismatchError: (diff) All the lenghts must be equal! ()

Matrix.from_transfer values exceeding matrix's member values

Relevant conversation on Discord

Simply put, when trying to get the Matrix from an HDR source, it attempts to get Matrix(16). Matrix doesn't have a member with the value of 16, so this causes an error. This problem may also persist with Primaries.

2023-11-15 17:18:39.522: root: ERROR: ValueError: 16 is not a valid Matrix
...
  File "C:\Users\oliwis\AppData\Local\Programs\Python\Python311\Lib\site-packages\vskernels\kernels\complex.py", line 60, in func
    with LinearLight(clip, linear, sigmoid, self, kwargs.pop('format', None)) as ll:
  File "C:\Users\oliwis\AppData\Local\Programs\Python\Python311\Lib\site-packages\vskernels\util.py", line 226, in __enter__
    self._matrix = Matrix.from_transfer(self._curve)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

padder feature additions

Currently padder only pads with mirror and repeat padding, ideally it should support all modes fillborders provides and additionally act as an std.AddBorders wrapper allowing users to create padding with a specific color.

Chroma location heuristic is flawed for 4K video

The check should not be based on res at all, it should be dependant on the colorspace of the input. Top left location is defined by Rec. BT.2020 and as such should only be set to top left if the video is BT.2020, otherwise left should be assumed.

TypeError: multiple bases have instance lay-out conflict

2023-02-15 20:15:50.899: root: ERROR: multiple bases have instance lay-out conflict
2023-02-15 20:15:50.918: root: ERROR: Traceback (most recent call last):
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\lvsfunc\comparison.py", line 651, in diff
    raise CustomError[StopIteration]('No differences found!', diff)
          ~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\exceptions\base.py", line 107, in __class_getitem__
    class inner_exception(cls, exception):  # type: ignore
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\exceptions\base.py", line 34, in __new__
    return CustomErrorMeta.setup_exception(type.__new__(cls, *args))  # type: ignore
                                           ^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: multiple bases have instance lay-out conflict

Inconsistent method names

A handful of method names are inconsistent throughout this package (and other iew packages),
and I cannot really determine any logic behind some of them.

This is the one I thought of right now, but there are more.

image
image

If I remember or find more, I will add them in a comment (and reopen if necessary).
If any of the listed ones do have some logic behind them, simply mark those specific instances as wontfix.

`norm_func_name` errors on instance method

From norm_func_name in normalize.py:

    if callable(func):
        if hasattr(func, '__self__'):
            func_name = f'{func.__self__.__name__}.{func_name}'

This code path is taken even if func.__name__ or func.__qualname__ exist, and would override those values. I can't really tell if this is intended, but it seems reasonable. However, if called on an instance method, __self__ refers to the instance, which doesn't have a __name__:

>>> from vstools import norm_func_name as norm
>>> class A():
...     def foo(self):
...             pass
...
>>> norm(A.foo)
'foo'
>>> a = A()
>>> norm(a.foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../site-packages/vstools/functions/normalize.py", line 285, in norm_func_name
    func_name = f'{func.__self__.__name__}.{func_name}'
                   ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'A' object has no attribute '__name__'. Did you mean: '__ne__'?

The correct behavior would be to access the instance's __class__ property instead:

>>> a.foo.__self__                     # instance
<__main__.A object at 0x0000015B8922BA10>
>>> a.foo.__self__.__class__           # class
<class '__main__.A'>
>>> a.foo.__self__.__class__.__name__  # desired name property
'A'

Note also that this only happens when referencing the function via an instance of the class (though this is probably much more common than referencing the class's function directly)

I think it would be best to first check if func.__self__ has a __name__ attribute, then if not, check if it has a __class__ attribute, and finally use that one's __name__. (Note that, for a class, A.__class__ is type, so both of these checks would be necessary)

finalize_clip errors if given a gray clip

  File "C:\Users\Reza\AppData\Roaming\Python\Python311\site-packages\vstools\utils\clips.py", line 68, in finalize_clip
    clip = clip.akarin.Expr([
           ^^^^^^^^^^^^^^^^^^
  File "src\\cython\\vapoursynth.pyx", line 2860, in vapoursynth.Function.__call__
vapoursynth.Error: Expr: More expressions given than there are planes

AttributeError: 'NoneType' object has no attribute 'isatty'

When importing lvsfunc or vsaa i get error
AttributeError: 'NoneType' object has no attribute 'isatty'

The full traceback

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2890, in vapoursynth._vpy_evaluate
File "src\cython\vapoursynth.pyx", line 2891, in vapoursynth._vpy_evaluate
File "F:\test.vpy", line 6, in import lvsfunc
File "C:\Program Files\Python310\lib\site-packages\lvsfunc\__init__.py", line 12, in 
from . import (aa, comparison, deblock, dehalo, dehardsub, deinterlace, exceptions, fun, helpers, mask, misc, noise,
File "C:\Program Files\Python310\lib\site-packages\lvsfunc\aa.py", line 7, in 
from vskernels import Bicubic, Box, Catrom, Point
File "C:\Program Files\Python310\lib\site-packages\vskernels\__init__.py", line 15, in 
from . import exceptions, kernels, util
File "C:\Program Files\Python310\lib\site-packages\vskernels\exceptions.py", line 5, in 
from vstools import CustomValueError, FuncExceptT
File "C:\Program Files\Python310\lib\site-packages\vstools\__init__.py", line 1, in 
from .enums import * # noqa: F401, F403
File "C:\Program Files\Python310\lib\site-packages\vstools\enums\__init__.py", line 1, in 
from .base import * # noqa: F401, F403
File "C:\Program Files\Python310\lib\site-packages\vstools\enums\base.py", line 6, in 
from ..exceptions import NotFoundEnumValue
File "C:\Program Files\Python310\lib\site-packages\vstools\exceptions\__init__.py", line 1, in 
from .base import * # noqa: F401, F403
File "C:\Program Files\Python310\lib\site-packages\vstools\exceptions\base.py", line 40, in 
class CustomError(Exception, metaclass=CustomErrorMeta):
File "C:\Program Files\Python310\lib\site-packages\vstools\exceptions\base.py", line 32, in __new__
if sys.stdout.isatty():
AttributeError: 'NoneType' object has no attribute 'isatty'

I've updated lvsfunc, vsaa and vstools from git passing the --upgrade flag to pip.

`normalize_ranges` treated as exclusive?

When pushing a list of range through normalize_ranges, the final frame gets treated as if it's exclusive in a sense.

[(100, 200)]

->

[(100, 199)]

This causes scenefiltering to be off by one frame.

Format exceptions add useful information

It would be nice if Exceptions like for example FormatsRefClipMismatchError would also display the formats of both clips in the reason by default. This makes it much easier to see which clip needs adjusting.

Keyframes: xvid keyframe file not parsed correctly.

My xvid keyframe files are in this format:

# XviD 2pass stat file (core version 1.4.-127)
# Please do not modify this file

i 2 920 0 0 2710 2710
p 2 0 0 920 232 232
p 2 0 0 920 232 232
p 2 0 0 920 232 232
p 2 0 0 920 232 232
p 2 0 0 920 232 232

I am not sure whether this is the standard format or not, but it's what my SCXvid.exe spits out.

vstools appears to attempt to parse this sort of file here: https://github.com/Jaded-Encoding-Thaumaturgy/vs-tools/blob/master/vstools/functions/timecodes.py#L458

This fails, but if I change lines[0].lower() to lines[0].lower()[0] and then also modify https://github.com/Jaded-Encoding-Thaumaturgy/vs-tools/blob/master/vstools/functions/timecodes.py#L465 in the same way, it appears to work correctly.

Full keyframe file: attackTwo01_keyframes.txt

File type parsing improve heuristics

With certain files, the wrong filetype appears to be getting parsed.

For example, this m2ts file prases as an AC3 file.

ParsedFile(path=WindowsPath('C:/Users/light/Encoding/temp/maria/00002.m2ts'), ext='.ac3', encoding=None, file_type=<FileType.AUDIO: 'audio'>, mime='application/octet-stream')

ffprobe's results:

Input #0, mpegts, from '00002.m2ts':
  Duration: 00:25:27.87, start: 5614.566667, bitrate: 42425 kb/s
  Program 1
  Stream #0:0[0x1011]: Video: h264 (High) (HDMV / 0x564D4448), yuv420p(tv, bt709, top first), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn
  Stream #0:1[0x1100]: Audio: pcm_bluray (HDMV / 0x564D4448), 48000 Hz, stereo, s16, 1536 kb/s
  Stream #0:2[0x1101]: Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, stereo, fltp, 448 kb/s

The first couple bytes

file_bytes=b'\x0bw\\\xccG@\x00\x10\x00\x00\xb0\x11\x00\x00\xc1\x00\x00\x00'

This file gets parsed correctly upon any form of remuxing, even when trying to generate a test clip using the following command:

ffmpeg -to 0:03.00 -i "00002.m2ts" -c copy test.m2ts

Having additional heuristics to determine a file type would be appreciated, but I'm not sure how much can be done here.
One kind of hacky solution I can think of for vssource.source is to check if a video is parsed as anything but VIDEO/IMAGE, and then try simpler heuristics and see if those return a video or image.

invert_ranges: Does not return proper ranges

This is really an issue with replace_ranges, but I could trace it as far back as invert_ranges I believe.
From what I can gather, it does not properly return an inversion of the ranges, so replace_ranges' a_trims becomes a single clip the length of the original clip as opposed to the two necessary. The b_trims get appended at the end instead of sandwiched between them as it should.

    out = replace_ranges(clip, clip.std.BlankClip(keep=True), [(1000, 9000)])
    print("og clip", clip.num_frames)
    print("out clip", out.num_frames)
og clip 34765
out clip 42766

Clips passed to replace_ranges:

VideoNode
        Format: YUV420P16
        Width: 1920
        Height: 1080
        Num Frames: 34765
        FPS: 24000/1001

 VideoNode
        Format: YUV420P16
        Width: 1920
        Height: 1080
        Num Frames: 34765
        FPS: 24000/1001

a and b_ranges

[(0, 34764)]
[(1000, 9000)]

Suggestion: Additional Keyframes and Timecodes methods

It would be nice if we could get additional methods to obtain Keyframes and Timecodes objects.

.from_list

The first suggestion would be for Keyframes: .from_list.
This would simply call __init__ and pass the iterator.
The purpose of this is more so just to have a convenience function for people looking for it who aren't aware you can just pass a list directly to the class.

.from_wobbly

The next one is a convenience method for wobbly usage and to speed up parsing, for both Keyframes and Timecodes.
This would go together with eventually(?) wobbly/wibbly updates in vsdeinterlace.
This should simply read the .wob file and construct the relevant object (from which the user can then write it to a file).

Merge padder and mod_padding

Currently DPIR and Waifu2x both have their own implementations of mod_padding (with DPIR's giving incorrect results). Instead of duplicating code just implement the functionality into padder.

Core proxy

foo.py

from vstools import vs
import vapoursynth
resizer = vs.core.resize.Bicubic

def get_resizer():
    print('VS core:', vapoursynth.core)
    print('vstools core:', vs.core)
    return resizer

Untitled.vpy

from foo import *clip = vs.core.std.BlankClip()

clip = get_resizer()(clip)

clip.set_output()

vsedit Untitled.vpy with F6 script checking (where VS core is acquired from the newly created script, and pointers are printed to stdout):

VS core: <vapoursynth._CoreProxy object at 0x7f0cf0188bb0>
vstools core: <vstools.utils.vs_proxy.VSCoreProxy object at 0x7f0ceaa61120>
Current core: 0x55f2b65b1f60
Current script: 0x55f2b65cd130
VS core: <vapoursynth._CoreProxy object at 0x7f0cf0188bb0>
vstools core: <vstools.utils.vs_proxy.VSCoreProxy object at 0x7f0ceaa61120>
Current core: 0x55f2b5be6ca0
Current script: 0x7f0cec007060

`normalize_list_to_ranges` `IndexError` with certain inputs

This error pops up when using normalize_ranges (such as in replace_ranges) with specific input. The error originates from normalize_list_to_ranges.

Input:

[45, 46, 47, 48, 49, 50, 51, 210, 211, 212, 213, 214, 215, 216, 820, 824, 825, 829, 830, 834, 835, 839, 840, 1584, 1585, 1586, 1587, 1596, 1597, 1598, 1599, 1600, 1609, 1610, 1611, 1612, 1613, 1623, 1624, 1625, 1626, 1636, 1637, 1638, 1639, 1651, 1652, 1653, 1654, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1713, 1714, 1715, 1717, 1723, 2354, 2412]

normalize_ranges output that gets passed on to normalize_list_to_ranges:

[(45, 45), (46, 46), (47, 47), (48, 48), (49, 49), (50, 50), (51, 51), (210, 210), (211, 211), (212, 212), (213, 213), (214, 214), (215, 215), (216, 216), (820, 820), (824, 824), (825, 825), (829, 829), (830, 830), (834, 834), (835, 835), (839, 839), (840, 840), (1584, 1584), (1585, 1585), (1586, 1586), (1587, 1587), (1596, 1596), (1597, 1597), (1598, 1598), (1599, 1599), (1600, 1600), (1609, 1609), (1610, 1610), (1611, 1611), (1612, 1612), (1613, 1613), (1623, 1623), (1624, 1624), (1625, 1625), (1626, 1626), (1636, 1636), (1637, 1637), (1638, 1638), (1639, 1639), (1651, 1651), (1652, 1652), (1653, 1653), (1654, 1654), (1677, 1677), (1678, 1678), (1679, 1679), (1680, 1680), (1681, 1681), (1682, 1682), (1683, 1683), (1713, 1713), (1714, 1714), (1715, 1715), (1717, 1717), (1723, 1723), (2354, 2354), (2412, 2412)]

Error in normalize_list_to_ranges:

  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\utils\ranges.py", line 82, in replace_ranges
    nranges = normalize_ranges(clip_b, ranges)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\functions\normalize.py", line 251, in normalize_ranges
    return normalize_list_to_ranges([
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\functions\normalize.py", line 192, in normalize_list_to_ranges
    [i[-1 if j == last_idx else -2] for j, i in enumerate(flist4)]
  File "C:\Users\light\AppData\Local\Programs\Python\Python311\Lib\site-packages\vstools\functions\normalize.py", line 192, in <listcomp>
    [i[-1 if j == last_idx else -2] for j, i in enumerate(flist4)]
     ~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndexError: list index out of range

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.