1
0
mirror of https://github.com/Zulko/moviepy.git synced 2021-07-27 01:17:47 +03:00

Setup 'isort' and 'pre-commit' (#1479)

* Setup 'isort' and 'pre-commit'

* Check imports of examples in CI

* Only install isort in isort check job

* Remove testing and linting sections from README

* Remove uneeded lines

* Include maintainer line

* Lowercase isort

* Add TESTS section to isort config
This commit is contained in:
Álvaro Mondéjar
2021-01-22 12:25:04 +01:00
committed by GitHub
parent 2482d139dd
commit 8cc3eebb09
54 changed files with 147 additions and 121 deletions

View File

@@ -6,4 +6,3 @@ Delete them if they are not appropriate for this pull request.
- [ ] I have added suitable tests demonstrating a fixed bug or new/changed feature to the test suite in `tests/`
- [ ] I have properly documented new or changed features in the documentation or in the docstrings
- [ ] I have properly explained unusual or unexpected code in the comments around it
- [ ] I have formatted my code using `black -t py36`

View File

@@ -34,3 +34,18 @@ jobs:
run: flake8 tests --show-source
- name: Lint moviepy
run: flake8 moviepy --show-source
isort:
runs-on: ubuntu-latest
name: isort
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install isort
- name: Check imports
run: isort --check-only moviepy tests examples docs/conf.py

22
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,22 @@
repos:
- repo: https://gitlab.com/pycqa/flake8
rev: master
hooks:
- id: flake8
additional_dependencies:
- flake8-implicit-str-concat
- flake8-absolute-import
name: flake8-test
files: \.py$
- repo: https://github.com/PyCQA/isort
rev: master
hooks:
- id: isort
args: ['--check-only', '--filter-files']
files: \.py$
- repo: https://github.com/psf/black
rev: stable
hooks:
- id: black
language_version: python3.6
files: \.py$

View File

@@ -8,6 +8,7 @@
- Do not push any commit that changes the API without prior discussion.
## Preparing for development
- Fork the official MoviePy repository to your own GitHub account:
Use the "Fork" button in the top right corner of the GitHub interface while viewing [the official MoviePy](https://github.com/Zulko/moviepy) repository.
- Use your fork as the basis for cloning the repository to your local machine: `$ git clone URL_TO_YOUR_FORK`
@@ -15,15 +16,15 @@ You can get the appropriate URL (SSH- or HTTPS-based) by using the green "Code"
- Enter your local clone and add the official MoviePy repository as a second remote, with alias `upstream`:
`$ git remote add upstream git@github.com:Zulko/moviepy.git` (using SSL) _or_
`$ git remote add upstream https://github.com/Zulko/moviepy.git` (using HTTPS).
- Install the library inside a [virtual environment](https://docs.python.org/3/tutorial/venv.html) with all dependencies included using `$ pip install -e ".[optional,doc,test,lint]"`
- Configure pre-commit hooks running `$ pre-commit install`
## Coding conventions, code quality
- Respect [PEP8](https://www.python.org/dev/peps/pep-0008/) conventions.
- Add just the "right" amount of comments. Try to write auto-documented code with very explicit variable names.
- If you introduce new functionality or fix a bug, document it in the docstring or with code comments.
- MoviePy's team adopted [black](https://github.com/psf/black) to autoformat code. This is enforced for any pull request.
> Tip: use `black -t py36 .` to autoformat your code, or set black as a [plugin for your editor](https://black.readthedocs.io/en/stable/editor_integration.html).
- MoviePy's team adopted [pre-commit](https://pre-commit.com/) to run code checks using black, flake8 and isort, so make sure that you've configured the pre-commit hooks with `pre-commit install`.
## Standard contribution workflow
@@ -48,7 +49,6 @@ You do not have to have finished your feature or bug fix before submitting a PR;
Before submitting PRs:
- make sure your code still conforms to the formatting standard (using Black formatter: `$ black -t py36 .`)
- run the test suite over your code to expose any problems: `$ pytest`
- push your local develop branch to your GitHub fork `$ git push origin YOUR_DEVELOP_BRANCH`

View File

@@ -48,7 +48,7 @@ In this example we open a video file, select the subclip between t=50s and t=60s
Maintainers wanted!
-------------------
As there are more and more people seeking support (320 open issues as of Sept. 2019!) and all the MoviePy maintainers seem busy, we'd love to hear about developers interested in giving a hand and solving some of the issues (especially the ones that affect you) or reviewing pull requests. Open an issue or contact us directly if you are interested. Thanks!
As there are more and more people seeking support (270 open issues as of Jan. 2021!) and all the MoviePy maintainers seem busy, we'd love to hear about developers interested in giving a hand and solving some of the issues (especially the ones that affect you) or reviewing pull requests. Open an issue or contact us directly if you are interested. Thanks!
Installation
------------
@@ -103,7 +103,7 @@ For instance, using the method ``clip.resize`` requires that at least one of Sci
Documentation
-------------
Running `build_docs` has additional dependencies that require installation.
Building the documentation has additional dependencies that require installation.
.. code:: bash
@@ -148,44 +148,6 @@ Then at the beginning of your notebook enter:
Have a look at the Proglog project page for more options.
Running Tests
-------------
In order to run the test suite locally, first install the dependencies by navigating to the project directory and running:
.. code:: bash
$ (sudo) pip install moviepy[test]
The test suite can then be executed via:
.. code:: bash
$ pytest
Linting and formatting
----------------------
To make sure that all the code is well formatted and consistent, we use Black_ and Flake8_. Install them by navigating to the project directory and running:
.. code:: bash
$ (sudo) pip install moviepy[lint]
You can lint all files running:
.. code:: bash
$ flake8
To format the files properly use:
.. code:: bash
$ black -t py36 .
Contribute
----------
@@ -205,6 +167,7 @@ Maintainers
- `@overdrivr`_
- `@keikoro`_
- `@ryanfox`_
- `@mondeja`_
.. MoviePy links
@@ -234,8 +197,6 @@ Maintainers
.. _ImageMagick: https://www.imagemagick.org/script/index.php
.. _`Matplotlib`: https://matplotlib.org/
.. _`Sphinx`: https://www.sphinx-doc.org/en/master/setuptools.html
.. _`Black`: https://black.readthedocs.io/en/stable/
.. _`Flake8`: https://flake8.pycqa.org/en/latest/
.. People
.. _Zulko: https://github.com/Zulko
@@ -245,4 +206,5 @@ Maintainers
.. _`@mbeacom`: https://github.com/mbeacom
.. _`@overdrivr`: https://github.com/overdrivr
.. _`@keikoro`: https://github.com/keikoro
.. _`@ryanfox`: https://github.com/ryanfox
.. _`@ryanfox`: https://github.com/ryanfox
.. _`@mondeja`: https://github.com/mondeja

View File

@@ -14,10 +14,9 @@
import os
import sys
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
import sphinx_rtd_theme
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.

View File

@@ -1,6 +1,7 @@
from moviepy import *
from moviepy.video.tools.segmenting import find_objects
# Load the image specifying the regions.
im = ImageClip("../../ultracompositing/motif.png")

View File

@@ -26,6 +26,7 @@ from moviepy import *
from moviepy.audio.tools.cuts import find_audio_period
from moviepy.video.tools.cuts import find_video_period
# Next lines are for downloading the required videos from Youtube.
# To do this you must have youtube-dl installed, otherwise you will need to
# download the videos by hand and rename them, as follows:

View File

@@ -8,6 +8,7 @@ movie put together.
from moviepy import *
from moviepy.video.tools.drawing import color_split
duration = 6 # duration of the final clip
# LOAD THE MAIN SCENE

View File

@@ -1,6 +1,7 @@
from moviepy import *
from moviepy.video.tools.tracking import manual_tracking # noqa 401
from moviepy.video.tools.interpolators import Trajectory
from moviepy.video.tools.tracking import manual_tracking # noqa 401
# LOAD THE CLIP (subclip 6'51 - 7'01 of a chaplin movie)
clip = VideoFileClip("media/chaplin.mp4")

View File

@@ -2,6 +2,7 @@ import numpy as np
from moviepy import *
w, h = moviesize = (720, 380)
duration = 1

View File

@@ -1,6 +1,7 @@
from moviepy import *
from moviepy.video.tools.credits import credits1
# Load the mountains clip, cut it, slow it down, make it look darker
clip = (
VideoFileClip("../../videos/badl-0001.mov", audio=False)

View File

@@ -3,6 +3,7 @@ import numpy as np
from moviepy import *
from moviepy.video.tools.segmenting import find_objects
# WE CREATE THE TEXT THAT IS GOING TO MOVE, WE CENTER IT.
screensize = (720, 460)

View File

@@ -2,6 +2,7 @@
from moviepy import *
# WE TAKE THE SUBCLIPS WHICH ARE 2 SECONDS BEFORE & AFTER THE FREEZE
charade = VideoFileClip("../../videos/charade.mp4")

View File

@@ -1,6 +1,7 @@
""" A simple test script on how to put a soundtrack to a movie """
from moviepy import *
# We load a movie and replace the sound with some music:
movie = VideoFileClip("../../videos/dam.mov").with_audio(

View File

@@ -7,10 +7,11 @@ background made of stars. Slight fading effect on the text.
"""
import numpy as np
from skimage import transform as tf
from moviepy import *
from moviepy.video.tools.drawing import color_gradient
from skimage import transform as tf
# RESOLUTION

View File

@@ -1,6 +1,7 @@
from moviepy import *
from moviepy.video.tools.drawing import circle
clip = (
VideoFileClip("../../videos/badl-0006.mov", audio=False).subclip(26, 31).add_mask()
)

View File

@@ -1,5 +1,6 @@
from moviepy import *
# UKULELE CLIP, OBTAINED BY CUTTING AND CROPPING
# RAW FOOTAGE

View File

@@ -1,6 +1,7 @@
import re
from urllib import request
url = "https://legacy.imagemagick.org/script/index.php"
"""This little script parses url above to extract latest image magick version

View File

@@ -11,40 +11,31 @@ you can write ``clip.resize(2)``.
import inspect
from moviepy.version import __version__
# Clips
from moviepy.video.VideoClip import (
VideoClip,
ImageClip,
ColorClip,
TextClip,
BitmapClip,
)
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip, clips_array
from moviepy.video.io.ImageSequenceClip import ImageSequenceClip
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.io.downloader import download_webfile
from moviepy.audio import fx as afx
from moviepy.audio.AudioClip import (
AudioClip,
CompositeAudioClip,
concatenate_audioclips,
)
from moviepy.audio.io.AudioFileClip import AudioFileClip
# FX
from moviepy.video import fx as vfx
from moviepy.audio import fx as afx
from moviepy.video.compositing import transitions as transfx
# Tools
from moviepy.video import tools as videotools
from moviepy.video.io import ffmpeg_tools
from moviepy.tools import convert_to_seconds
from moviepy.version import __version__
from moviepy.video import fx as vfx, tools as videotools
from moviepy.video.compositing import transitions as transfx
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip, clips_array
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.io import ffmpeg_tools
from moviepy.video.io.downloader import download_webfile
from moviepy.video.io.ImageSequenceClip import ImageSequenceClip
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.VideoClip import (
BitmapClip,
ColorClip,
ImageClip,
TextClip,
VideoClip,
)
# Transforms the effects into Clip methods so that
# they can be called with clip.resize(width=500) instead of

View File

@@ -7,6 +7,7 @@ from moviepy.audio.fx.audio_normalize import audio_normalize
from moviepy.audio.fx.multiply_stereo_volume import multiply_stereo_volume
from moviepy.audio.fx.multiply_volume import multiply_volume
__all__ = (
"audio_fadein",
"audio_fadeout",

View File

@@ -8,4 +8,5 @@ import warnings
from .. import * # noqa 401,F403
warnings.warn(f"\nMoviePy: {__doc__}", UserWarning)

View File

@@ -1,6 +1,5 @@
from moviepy.decorators import audio_video_fx
from moviepy.audio.fx.multiply_volume import multiply_volume
from moviepy.decorators import audio_video_fx
@audio_video_fx

View File

@@ -1,10 +1,11 @@
import time
import numpy as np
import pygame as pg
from moviepy.decorators import requires_duration
pg.init()
pg.display.set_caption("MoviePy")

View File

@@ -4,8 +4,8 @@ import warnings
import numpy as np
from moviepy.config import FFMPEG_BINARY
from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos
from moviepy.tools import cross_platform_popen_params
from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos
class FFMPEG_AudioReader:

View File

@@ -1,6 +1,6 @@
import os
from pathlib import Path
import subprocess as sp
from pathlib import Path
from moviepy.tools import cross_platform_popen_params
@@ -9,7 +9,7 @@ if os.name == "nt":
import winreg as wr
try:
from dotenv import load_dotenv, find_dotenv
from dotenv import find_dotenv, load_dotenv
DOTENV = find_dotenv()
load_dotenv(DOTENV)

View File

@@ -16,6 +16,7 @@ import moviepy # So that we can access moviepy.__all__ later
from moviepy import *
from moviepy.video.io.html_tools import ipython_display
try:
from moviepy.video.io.sliders import sliders
except ImportError:
@@ -39,7 +40,7 @@ os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1"
# Add methods preview and show (only if pygame installed)
try:
from moviepy.video.io.preview import show, preview
from moviepy.video.io.preview import preview, show
except ImportError:
def preview(self, *args, **kwargs):

View File

@@ -2,6 +2,7 @@ from moviepy.audio.io.AudioFileClip import AudioFileClip
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.VideoClip import ImageClip
CLIP_TYPES = {
"audio": AudioFileClip,
"video": VideoFileClip,

View File

@@ -4,22 +4,24 @@ main subclasses:
- Animated clips: VideofileClip, ImageSequenceClip
- Static image clips: ImageClip, ColorClip, TextClip,
"""
import copy as _copy
import os
import subprocess as sp
import tempfile
import copy as _copy
import numpy as np
import proglog
from imageio import imread, imsave
from PIL import Image
from moviepy.Clip import Clip
from moviepy.config import IMAGEMAGICK_BINARY
from moviepy.decorators import (
add_mask_if_none,
apply_to_mask,
convert_masks_to_RGB,
convert_path_to_string,
convert_parameter_to_seconds,
convert_path_to_string,
outplace,
requires_duration,
requires_fps,
@@ -38,7 +40,6 @@ from moviepy.video.io.gif_writers import (
write_gif_with_tempfiles,
)
from moviepy.video.tools.drawing import blit
from PIL import Image
class VideoClip(Clip):

View File

@@ -1,10 +1,8 @@
import numpy as np
from PIL import Image
from moviepy.audio.AudioClip import CompositeAudioClip
from moviepy.video.VideoClip import ColorClip, VideoClip
from PIL import Image
# CompositeVideoClip
class CompositeVideoClip(VideoClip):

View File

@@ -4,11 +4,10 @@ to be used with clip.fx. There are available as transfx.crossfadein etc.
"""
from moviepy.decorators import add_mask_if_none, requires_duration
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.fx.fadein import fadein
from moviepy.video.fx.fadeout import fadeout
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
__all__ = ["crossfadein", "crossfadeout", "slide_in", "slide_out", "make_loopable"]

View File

@@ -8,4 +8,5 @@ import warnings
from moviepy.video.fx import * # noqa F401,F403
warnings.warn(f"\nMoviePy: {__doc__}", UserWarning)

View File

@@ -1,5 +1,4 @@
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.fx.crop import crop

View File

@@ -1,5 +1,6 @@
import numpy as np
# ------- CHECKING DEPENDENCIES -----------------------------------------
try:
import cv2

View File

@@ -1,5 +1,6 @@
import numpy as np
# ------- CHECKING DEPENDENCIES -----------------------------------------
painting_possible = True
try:

View File

@@ -1,5 +1,6 @@
import numpy as np
try:
from PIL import Image

View File

@@ -1,6 +1,5 @@
from moviepy.decorators import apply_to_mask, requires_duration
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.fx.time_mirror import time_mirror

View File

@@ -8,6 +8,7 @@ from moviepy.config import FFMPEG_BINARY, IMAGEMAGICK_BINARY
from moviepy.decorators import requires_duration, use_clip_fps_by_default
from moviepy.tools import cross_platform_popen_params, subprocess_call
try:
import imageio

View File

@@ -14,9 +14,9 @@ from base64 import b64encode
from moviepy.audio.AudioClip import AudioClip
from moviepy.tools import extensions_dict
from moviepy.video.VideoClip import ImageClip, VideoClip
from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos
from moviepy.video.VideoClip import ImageClip, VideoClip
try:
from IPython.display import HTML

View File

@@ -2,12 +2,13 @@ import threading
import time
import numpy as np
import pygame as pg
from moviepy.decorators import convert_masks_to_RGB, requires_duration
from moviepy.tools import convert_to_seconds
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
pg.init()
pg.display.set_caption("MoviePy")

View File

@@ -11,10 +11,10 @@ of the tracking time interval).
import numpy as np
from moviepy.decorators import convert_parameter_to_seconds, use_clip_fps_by_default
from moviepy.video.io.preview import imdisplay
from moviepy.video.tools.interpolators import Trajectory
try:
import cv2

View File

@@ -15,3 +15,14 @@ per-file-ignores =
# Complexity should be decreased before uncomment:
#max-complexity = 10
[isort]
lines_after_imports = 2
multi_line_output = 3
line_length = 88
use_parentheses = True
combine_as_imports = True
include_trailing_comma = True
py_version = 36
known_tests = tests
sections = STDLIB,THIRDPARTY,FIRSTPARTY,TESTS,LOCALFOLDER

View File

@@ -8,6 +8,7 @@ and fail with a message if neither are successful.
import sys
from codecs import open
try:
from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand
@@ -109,6 +110,8 @@ lint_reqs = [
"flake8>3.7.0,<4.0.0",
"flake8-implicit-str-concat==0.2.0",
"flake8-absolute-import>=1.0",
"isort>=5.7.0",
"pre-commit>=2.9.3",
]
extra_reqs = {

View File

@@ -2,8 +2,8 @@
import os
import pytest
import numpy as np
import pytest
from moviepy.audio.AudioClip import (
AudioArrayClip,

View File

@@ -1,5 +1,5 @@
import pytest
import numpy as np
import pytest
from moviepy.video.VideoClip import BitmapClip

View File

@@ -10,7 +10,7 @@ from moviepy.utils import close_all_clips
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.fx.speedx import speedx
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.VideoClip import ColorClip, BitmapClip, VideoClip
from moviepy.video.VideoClip import BitmapClip, ColorClip, VideoClip
from tests.test_helper import TMP_DIR

View File

@@ -4,11 +4,11 @@ import os
import pytest
from moviepy.video.VideoClip import BitmapClip, ColorClip
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.compositing.CompositeVideoClip import clips_array
from moviepy.video.fx.resize import resize
from moviepy.utils import close_all_clips
from moviepy.video.compositing.CompositeVideoClip import clips_array
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.fx.resize import resize
from moviepy.video.VideoClip import BitmapClip, ColorClip
from tests.test_helper import TMP_DIR

View File

@@ -8,6 +8,7 @@ from moviepy.video.VideoClip import VideoClip
from tests.test_helper import TMP_DIR
try:
import matplotlib
except ImportError:

View File

@@ -3,14 +3,14 @@
import os
import subprocess
import pytest
import numpy as np
import pytest
from moviepy.config import FFMPEG_BINARY
from moviepy.audio.AudioClip import AudioClip
from moviepy.video.VideoClip import BitmapClip
from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos, FFMPEG_VideoReader
from moviepy.config import FFMPEG_BINARY
from moviepy.utils import close_all_clips
from moviepy.video.io.ffmpeg_reader import FFMPEG_VideoReader, ffmpeg_parse_infos
from moviepy.video.VideoClip import BitmapClip
from tests.test_helper import TMP_DIR

View File

@@ -1,6 +1,7 @@
import os
from moviepy.video.io.ffmpeg_tools import ffmpeg_stabilize_video
from tests.test_helper import TMP_DIR

View File

@@ -5,12 +5,10 @@ import numpy as np
import pytest
from moviepy import AudioClip, AudioFileClip, BitmapClip, ColorClip, VideoFileClip
from moviepy.audio.fx import audio_normalize
from moviepy.audio.fx import multiply_stereo_volume
from moviepy.audio.fx import audio_normalize, multiply_stereo_volume
from moviepy.utils import close_all_clips
from moviepy.video.fx import (
blackwhite,
multiply_color,
crop,
even_size,
fadein,
@@ -24,6 +22,7 @@ from moviepy.video.fx import (
margin,
mirror_x,
mirror_y,
multiply_color,
resize,
rotate,
speedx,

View File

@@ -3,6 +3,7 @@
import sys
import tempfile
PYTHON_VERSION = "%s.%s" % (sys.version_info.major, sys.version_info.minor)
TMP_DIR = tempfile.gettempdir() # because tempfile.tempdir is sometimes None

View File

@@ -1,19 +1,21 @@
"""Issue tests meant to be run with pytest."""
import pytest
import os
from moviepy.video.VideoClip import ColorClip, ImageClip, VideoClip
import pytest
from moviepy.audio.io.AudioFileClip import AudioFileClip
from moviepy.utils import close_all_clips
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.compositing.transitions import crossfadein, crossfadeout
from moviepy.video.fx.resize import resize
from moviepy.audio.io.AudioFileClip import AudioFileClip
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.utils import close_all_clips
from moviepy.video.VideoClip import ColorClip, ImageClip, VideoClip
from tests.test_helper import TMP_DIR
try:
import matplotlib
except ImportError:
@@ -268,10 +270,11 @@ def test_issue_359():
@pytest.mark.skipif(not matplotlib, reason="no matplotlib")
def test_issue_368():
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from sklearn import svm
from sklearn.datasets import make_moons
from moviepy.video.io.bindings import mplfig_to_npimage
plt.switch_backend("agg")

View File

@@ -2,12 +2,12 @@ import os
import pytest
from moviepy.video.tools.cuts import find_video_period
from moviepy.video.fx.resize import resize
from moviepy.utils import close_all_clips
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.video.fx.resize import resize
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.tools.cuts import find_video_period
from moviepy.video.tools.subtitles import SubtitlesClip, file_to_subtitles
from moviepy.video.VideoClip import ColorClip, TextClip