Esempio n. 1
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable('git'):
            self.fail('git executable not found; cannot deploy.')

        branch = self.detect_target_branch(target_url)

        with _temporary_folder(self.env) as path:
            ssh_command = None
            def git(args, **kwargs):
                kwargs['env'] = _patch_git_env(kwargs.pop('env', None),
                                               ssh_command)
                return Command(['git'] + args, cwd=path, **kwargs)

            for line in git(['init']).output:
                yield line
            ssh_command = self.update_git_config(path, target_url, branch,
                                                 credentials)
            for line in git(['remote', 'update']).output:
                yield line

            if git(['checkout', '-q', branch], silent=True).wait() != 0:
                git(['checkout', '-qb', branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(['add', '-f', '--all', '.']).output:
                yield line
            for line in git(['commit', '-qm', 'Synchronized build']).output:
                yield line
            for line in git(['push', 'origin', branch]).output:
                yield line
def process_svg_image(
    ctx,
    source_image,
    dst_filename,
    width=None,
    height=None,
    mode=None,
):
    if width is None and height is None:
        raise ValueError("Must specify at least one of width or height.")

    # Because Lektor doesn't have a generic find program (only imagemagick),
    # only *nix is supported for simplicity. Imagemagick will be used as the
    # fallback on Windows, but it won't work well...
    if os.name == 'nt':
        return process_image(ctx, source_image, dst_filename, width, height,
                             mode, 85)

    inkscape = locate_executable('inkscape')

    cmdline = [inkscape, source_image]

    if width is not None:
        cmdline += ["-w", str(width)]
    if height is not None:
        cmdline += ["-h", str(height)]

    # FIXME: This will only work with inkscape 1.0+
    cmdline += ["--export-filename", dst_filename]

    reporter.report_debug_info("inkscape cmd line", cmdline)
    portable_popen(cmdline).wait()
Esempio n. 3
0
 def merge_pot(self, from_filenames, to_filename):
     msgcat = locate_executable('msgcat')
     cmdline = [msgcat, "--use-first"]
     cmdline.extend(from_filenames)
     cmdline.extend(("-o", to_filename))
     reporter.report_debug_info('msgcat cmd line', cmdline)
     portable_popen(cmdline).wait()
 def merge_pot(self, from_filenames, to_filename):
     msgcat=locate_executable('msgcat')
     cmdline=[msgcat, "--use-first"]
     cmdline.extend(from_filenames)
     cmdline.extend(("-o", to_filename))
     reporter.report_debug_info('msgcat cmd line', cmdline)
     portable_popen(cmdline).wait()
Esempio n. 5
0
 def parse_templates(self, to_filename):
     pybabel=locate_executable('pybabel')
     if pybabel is None:
         pybabel="/usr/bin/pybabel"
     cmdline=[pybabel, 'extract', '-F', 'babel.cfg', "-o", to_filename, "./"]
     reporter.report_debug_info('pybabel cmd line', cmdline)
     portable_popen(cmdline).wait()
Esempio n. 6
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable("git"):
            self.fail("git executable not found; cannot deploy.")

        branch = self.detect_target_branch(target_url)

        with _temporary_folder(self.env) as path:
            ssh_command = None

            def git(args, **kwargs):
                kwargs["env"] = _patch_git_env(kwargs.pop("env", None),
                                               ssh_command)
                return Command(["git"] + args, cwd=path, **kwargs)

            for line in git(["init"]).output:
                yield line
            ssh_command = self.update_git_config(path, target_url, branch,
                                                 credentials)
            for line in git(["remote", "update"]).output:
                yield line

            if git(["checkout", "-q", branch], silent=True).wait() != 0:
                git(["checkout", "-qb", branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(["add", "-f", "--all", "."]).output:
                yield line
            for line in git(["commit", "-qm", "Synchronized build"]).output:
                yield line
            for line in git(["push", "origin", branch]).output:
                yield line
Esempio n. 7
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable("git"):
            self.fail("git executable not found; cannot deploy.")

        # When pushing to the username.github.io repo we need to push to
        # master, otherwise to gh-pages
        if target_url.host + ".github.io" == target_url.path.strip("/"):
            branch = "master"
        else:
            branch = "gh-pages"

        with _temporary_folder(self.env) as path:
            ssh_command = None

            def git(args, **kwargs):
                kwargs["env"] = _patch_git_env(kwargs.pop("env", None), ssh_command)
                return Command(["git"] + args, cwd=path, **kwargs).proc()

            for line in git(["init"]):
                yield line
            ssh_command = self.update_git_config(path, target_url, branch, credentials)
            for line in git(["remote", "update"]):
                yield line

            if git(["checkout", "-q", branch], silent=True).wait() != 0:
                git(["checkout", "-qb", branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(["add", "-f", "--all", "."]):
                yield line
            for line in git(["commit", "-qm", "Synchronized build"]):
                yield line
            for line in git(["push", "origin", branch]):
                yield line
Esempio n. 8
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable('git'):
            self.fail('git executable not found; cannot deploy.')

        branch = self.detect_target_branch(target_url)

        with _temporary_folder(self.env) as path:
            ssh_command = None

            def git(args, **kwargs):
                kwargs['env'] = _patch_git_env(kwargs.pop('env', None),
                                               ssh_command)
                return Command(['git'] + args, cwd=path, **kwargs)

            for line in git(['init']).output:
                yield line
            ssh_command = self.update_git_config(path, target_url, branch,
                                                 credentials)
            for line in git(['remote', 'update']).output:
                yield line

            if git(['checkout', '-q', branch], silent=True).wait() != 0:
                git(['checkout', '-qb', branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(['add', '-f', '--all', '.']).output:
                yield line
            for line in git(['commit', '-qm', 'Synchronized build']).output:
                yield line
            for line in git(['push', 'origin', branch]).output:
                yield line
Esempio n. 9
0
 def _msg_init(self):
     """Generates the first <language>.po file"""
     msginit = locate_executable('msginit')
     cmdline = [
         msginit, "-i", "contents.pot", "-l", self.language, "-o",
         self.FILENAME_PATTERN % self.language, "--no-translator"
     ]
     reporter.report_debug_info('msginit cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 10
0
 def _msg_merge(self):
     """Merges an existing <language>.po file with .pot file"""
     msgmerge = locate_executable('msgmerge')
     cmdline = [
         msgmerge, self.FILENAME_PATTERN % self.language, "contents.pot",
         "-U", "-N", "--backup=simple"
     ]
     reporter.report_debug_info('msgmerge cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 11
0
 def _msg_fmt(self, locale_dirname):
     """Compile an existing <language>.po file into a .mo file"""
     msgfmt = locate_executable('msgfmt')
     cmdline = [
         msgfmt, self.FILENAME_PATTERN % self.language, "-o",
         join(locale_dirname, "contents.mo")
     ]
     reporter.report_debug_info('msgfmt cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 12
0
 def parse_templates(self, to_filename):
     pybabel = locate_executable('pybabel')
     cmdline = [
         pybabel, 'extract', '-F', 'babel.cfg', "-o", to_filename, "./"
     ]
     reporter.report_debug_info('pybabel cmd line', cmdline)
     try:
         portable_popen(cmdline).wait()
     except TypeError as err:
         traceback.print_exc(file=sys.stderr)
         print(err)
Esempio n. 13
0
 def run_package_manager(self, *args):
     # Use yarn over npm if it's availabe and there is a yarn lockfile
     has_yarn_lockfile = os.path.exists(
         self.get_webpack_folder('yarn.lock'))
     pkg_manager = 'npm'
     if locate_executable('yarn') is not None and has_yarn_lockfile:
         pkg_manager = 'yarn'
     reporter.report_generic('Running {} {}'.format(pkg_manager,
                                                    " ".join(args)))
     return portable_popen([pkg_manager] + list(args),
                           cwd=self.get_webpack_folder())
Esempio n. 14
0
    def install_node_dependencies(self):
        webpack_root = os.path.join(self.env.root_path, 'webpack')

        # Use yarn over npm if it's availabe and there is a yarn lockfile
        has_yarn_lockfile = os.path.exists(
            os.path.join(webpack_root, 'yarn.lock'))
        pkg_manager = 'npm'
        if locate_executable('yarn') is not None and has_yarn_lockfile:
            pkg_manager = 'yarn'

        reporter.report_generic('Running {} install'.format(pkg_manager))
        portable_popen([pkg_manager, 'install'], cwd=webpack_root).wait()
Esempio n. 15
0
def get_video_info(filename):
    """Read video information using ffprobe if available.

    Returns a dict with: width, height and duration.
    """
    ffprobe = locate_executable("ffprobe")
    if ffprobe is None:
        raise RuntimeError("Failed to locate ffprobe")

    proc = portable_popen(
        [
            ffprobe,
            "-v",
            "quiet",
            "-print_format",
            "json",
            "-show_format",
            "-show_streams",
            filename,
        ],
        stdout=subprocess.PIPE,
    )
    stdout, _ = proc.communicate()

    if proc.returncode != 0:
        raise RuntimeError("ffprobe exited with code %d" % proc.returncode)

    ffprobe_data = json.loads(stdout.decode("utf8"))
    info = {
        "width": None,
        "height": None,
        "duration": None,
    }

    # Try to extract total video duration
    try:
        info["duration"] = timedelta(
            seconds=float(ffprobe_data["format"]["duration"]))
    except (KeyError, TypeError, ValueError):
        pass

    # Try to extract width and height from the first found video stream
    for stream in ffprobe_data["streams"]:
        if stream["codec_type"] != "video":
            continue

        info["width"] = int(stream["width"])
        info["height"] = int(stream["height"])

        # We currently don't bother with multiple video streams
        break

    return info
Esempio n. 16
0
def get_video_info(filename):
    """Read video information using ffprobe if available.

    Returns a dict with: width, height and duration.
    """
    ffprobe = locate_executable('ffprobe')
    if ffprobe is None:
        raise RuntimeError('Failed to locate ffprobe')

    proc = portable_popen([
        ffprobe,
        '-v', 'quiet',
        '-print_format', 'json',
        '-show_format',
        '-show_streams',
        filename,
    ], stdout=subprocess.PIPE)
    stdout, _ = proc.communicate()

    if proc.returncode != 0:
        raise RuntimeError('ffprobe exited with code %d' % proc.returncode)

    ffprobe_data = json.loads(stdout.decode("utf8"))
    info = {
        'width': None,
        'height': None,
        'duration': None,
    }

    # Try to extract total video duration
    try:
        info['duration'] = timedelta(
            seconds=float(ffprobe_data['format']['duration']))
    except (KeyError, TypeError, ValueError):
        pass

    # Try to extract width and height from the first found video stream
    for stream in ffprobe_data['streams']:
        if stream['codec_type'] != 'video':
            continue

        info['width'] = int(stream['width'])
        info['height'] = int(stream['height'])

        # We currently don't bother with multiple video streams
        break

    return info
Esempio n. 17
0
def find_imagemagick(im=None):
    """Finds imagemagick and returns the path to it."""
    # If it's provided explicitly and it's valid, we go with that one.
    if im is not None and os.path.isfile(im):
        return im

    # On windows, imagemagick was renamed to magick, because
    # convert is system utility for fs manipulation.
    imagemagick_exe = "convert" if os.name != "nt" else "magick"

    rv = locate_executable(imagemagick_exe)
    if rv is not None:
        return rv

    # Give up.
    raise RuntimeError("Could not locate imagemagick.")
Esempio n. 18
0
def find_imagemagick(im=None):
    """Finds imagemagick and returns the path to it."""
    # If it's provided explicitly and it's valid, we go with that one.
    if im is not None and os.path.isfile(im):
        return im

    # If we have a shipped imagemagick, then we used this one.
    if BUNDLE_BIN_PATH is not None:
        executable = os.path.join(BUNDLE_BIN_PATH, 'convert')
        if os.name == 'nt':
            executable += '.exe'
        if os.path.isfile(executable):
            return executable

    # If we're not on windows, we locate the executable like we would
    # do normally.
    if os.name != 'nt':
        rv = locate_executable('convert')
        if rv is not None:
            return rv

    # On windows, we only scan the program files for an image magick
    # installation, because this is where this usually goes.  We do
    # this because the convert executable is otherwise the system
    # one which can convert file systems and stuff like this.
    else:
        for key in 'ProgramFiles', 'ProgramW6432', 'ProgramFiles(x86)':
            value = os.environ.get(key)
            if not value:
                continue
            try:
                for filename in os.listdir(value):
                    if filename.lower().startswith('imagemagick-'):
                        exe = os.path.join(value, filename, 'convert.exe')
                        if os.path.isfile(exe):
                            return exe
            except OSError:
                continue

    # Give up.
    raise RuntimeError('Could not locate imagemagick.')
Esempio n. 19
0
def find_imagemagick(im=None):
    """Finds imagemagick and returns the path to it."""
    # If it's provided explicitly and it's valid, we go with that one.
    if im is not None and os.path.isfile(im):
        return im

    # If we have a shipped imagemagick, then we used this one.
    if BUNDLE_BIN_PATH is not None:
        executable = os.path.join(BUNDLE_BIN_PATH, 'convert')
        if os.name == 'nt':
            executable += '.exe'
        if os.path.isfile(executable):
            return executable

    # If we're not on windows, we locate the executable like we would
    # do normally.
    if os.name != 'nt':
        rv = locate_executable('convert')
        if rv is not None:
            return rv

    # On windows, we only scan the program files for an image magick
    # installation, because this is where this usually goes.  We do
    # this because the convert executable is otherwise the system
    # one which can convert file systems and stuff like this.
    else:
        for key in 'ProgramFiles', 'ProgramW6432', 'ProgramFiles(x86)':
            value = os.environ.get(key)
            if not value:
                continue
            try:
                for filename in os.listdir(value):
                    if filename.lower().startswith('imagemagick-'):
                        exe = os.path.join(value, filename, 'convert.exe')
                        if os.path.isfile(exe):
                            return exe
            except OSError:
                continue

    # Give up.
    raise RuntimeError('Could not locate imagemagick.')
Esempio n. 20
0
def get_default_author_email() -> Optional[str]:
    """Attempt to guess an email address for the current user.

    May return an empty string if not reasonable guess can be made.
    """
    git = locate_executable("git")
    if git:
        proc = run((git, "config", "user.email"),
                   stdout=PIPE,
                   errors="strict",
                   check=False)
        if proc.returncode == 0:
            return proc.stdout.strip()

    email = os.environ.get("EMAIL", "").strip()
    if email:
        return email
    # We could fall back to f"{getpass.getuser()}@{socket.getfqdn()}",
    # but it is probably better just to go with no default in that
    # case.
    return None
Esempio n. 21
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable('git'):
            self.fail('git executable not found; cannot deploy.')

        # When pushing to the username.github.io repo we need to push to
        # master, otherwise to gh-pages
        if target_url.host + '.github.io' == target_url.path.strip('/'):
            branch = 'master'
        else:
            branch = 'gh-pages'

        with _temporary_folder(self.env) as path:
            ssh_command = None

            def git(args, **kwargs):
                kwargs['env'] = _patch_git_env(kwargs.pop('env', None),
                                               ssh_command)
                return Command(['git'] + args, cwd=path, **kwargs)

            for line in git(['init']).output:
                yield line
            ssh_command = self.update_git_config(path, target_url, branch,
                                                 credentials)
            for line in git(['remote', 'update']).output:
                yield line

            if git(['checkout', '-q', branch], silent=True).wait() != 0:
                git(['checkout', '-qb', branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(['add', '-f', '--all', '.']).output:
                yield line
            for line in git(['commit', '-qm', 'Synchronized build']).output:
                yield line
            for line in git(['push', 'origin', branch]).output:
                yield line
Esempio n. 22
0
    def publish(self, target_url, credentials=None):
        if not locate_executable('git'):
            raise PublishError('git executable not found; cannot deploy.')

        # When pushing to the username.github.io repo we need to push to
        # master, otherwise to gh-pages
        if target_url.host + '.github.io' == target_url.path.strip('/'):
            branch = 'master'
        else:
            branch = 'gh-pages'

        with self.temporary_repo() as path:

            def git(args, capture=True):
                cmd = Command(['git'] + args, cwd=path, capture=capture)
                if capture:
                    return cmd.safe_iter()
                return cmd

            for line in git(['init']):
                yield line
            self.update_git_config(path, target_url, branch, credentials)
            for line in git(['remote', 'update']):
                yield line

            if git(['checkout', '-q', branch], capture=False).wait() != 0:
                git(['checkout', '-qb', branch], capture=False).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(['add', '-f', '--all', '.']):
                yield line
            for line in git(['commit', '-qm', 'Synchronized build']):
                yield line
            for line in git(['push', 'origin', branch]):
                yield line
Esempio n. 23
0
def find_imagemagick(im=None):
    """Finds imagemagick and returns the path to it."""
    # If it's provided explicitly and it's valid, we go with that one.
    if im is not None and os.path.isfile(im):
        return im

    # On windows, imagemagick was renamed to magick, because
    # convert is system utility for fs manipulation.
    imagemagick_exe = 'convert' if os.name != 'nt' else 'magick'

    # If we have a shipped imagemagick, then we used this one.
    if BUNDLE_BIN_PATH is not None:
        executable = os.path.join(BUNDLE_BIN_PATH, imagemagick_exe)
        if os.name == 'nt':
            executable += '.exe'
        if os.path.isfile(executable):
            return executable

    rv = locate_executable(imagemagick_exe)
    if rv is not None:
        return rv

    # Give up.
    raise RuntimeError('Could not locate imagemagick.')
Esempio n. 24
0
    def publish(self, target_url, credentials=None, **extra):
        if not locate_executable('git'):
            self.fail('git executable not found; cannot deploy.')

        # When pushing to the username.github.io repo we need to push to
        # master, otherwise to gh-pages
        if target_url.host + '.github.io' == target_url.path.strip('/'):
            branch = 'master'
        else:
            branch = 'gh-pages'

        with _temporary_folder(self.env) as path:
            ssh_command = None
            def git(args, **kwargs):
                kwargs['env'] = _patch_git_env(kwargs.pop('env', None),
                                               ssh_command)
                return Command(['git'] + args, cwd=path, **kwargs).proc()

            for line in git(['init']):
                yield line
            ssh_command = self.update_git_config(path, target_url, branch,
                                                 credentials)
            for line in git(['remote', 'update']):
                yield line

            if git(['checkout', '-q', branch], silent=True).wait() != 0:
                git(['checkout', '-qb', branch], silent=True).wait()

            self.link_artifacts(path)
            self.write_cname(path, target_url)
            for line in git(['add', '-f', '--all', '.']):
                yield line
            for line in git(['commit', '-qm', 'Synchronized build']):
                yield line
            for line in git(['push', 'origin', branch]):
                yield line
Esempio n. 25
0
def find_imagemagick(im=None):
    """Finds imagemagick and returns the path to it."""
    # If it's provided explicitly and it's valid, we go with that one.
    if im is not None and os.path.isfile(im):
        return im

    # On windows, imagemagick was renamed to magick, because
    # convert is system utility for fs manipulation.
    imagemagick_exe = 'convert' if os.name != 'nt' else 'magick'

    # If we have a shipped imagemagick, then we used this one.
    if BUNDLE_BIN_PATH is not None:
        executable = os.path.join(BUNDLE_BIN_PATH, imagemagick_exe)
        if os.name == 'nt':
            executable += '.exe'
        if os.path.isfile(executable):
            return executable

    rv = locate_executable(imagemagick_exe)
    if rv is not None:
        return rv

    # Give up.
    raise RuntimeError('Could not locate imagemagick.')
Esempio n. 26
0
def test_default_author_from_pwd(mocker):
    pw_gecos = "Lektor Tester,,555-1212,,"
    mocker.patch("pwd.getpwuid",
                 spec=True,
                 return_value=struct_passwd(pw_gecos=pw_gecos))
    assert get_default_author() == "Lektor Tester"


def test_default_author_from_username(mocker):
    mocker.patch("getpass.getuser", spec=True, return_value="lektortester")
    if os.name != "nt":
        mocker.patch("os.getuid", spec=True, return_value=-1)
    assert get_default_author() == "lektortester"


@pytest.mark.skipif(locate_executable("git") is None,
                    reason="git not installed")
def test_default_author_email(git_config_file):
    git_config_file.write_text("[user]\n\temail = [email protected]\n")
    assert get_default_author_email() == "*****@*****.**"


@pytest.mark.usefixtures("no_utils")
def test_default_author_email_from_EMAIL(monkeypatch):
    email = "*****@*****.**"
    monkeypatch.setitem(os.environ, "EMAIL", email)
    assert get_default_author_email() == email


@pytest.mark.usefixtures("no_utils")
def test_default_author_email_no_default(monkeypatch):
Esempio n. 27
0
import os
from datetime import timedelta

import pytest

from lektor.utils import locate_executable
from lektor.videotools import Dimensions
from lektor.videotools import get_ffmpeg_quality
from lektor.videotools import get_timecode

has_ffmpeg = locate_executable("ffmpeg")
has_ffprobe = locate_executable("ffprobe")
require_ffmpeg = pytest.mark.skipif(
    not has_ffmpeg or not has_ffprobe,
    reason="requires ffmpeg and ffprobe in path")


@pytest.mark.parametrize(
    "td, tc",
    [
        (timedelta(), "00:00:00"),
        (timedelta(seconds=1), "00:00:01"),
        (timedelta(seconds=1.5), "00:00:01.5"),
        (timedelta(hours=8, minutes=15), "08:15:00"),
        (timedelta(hours=36, minutes=35, seconds=34.25), "36:35:34.25"),
    ],
)
def test_get_timecode(td, tc):
    assert get_timecode(td) == tc

Esempio n. 28
0
def make_video_thumbnail(
    ctx,
    source_video,
    source_url_path,
    seek,
    width=None,
    height=None,
    mode=ThumbnailMode.DEFAULT,
    upscale=None,
    quality=None,
    format=None,
):
    if mode != ThumbnailMode.FIT and (width is None or height is None):
        msg = '"%s" mode requires both `width` and `height` to be defined.'
        raise ValueError(msg % mode.label)

    if upscale is None:
        upscale = {
            ThumbnailMode.FIT: False,
            ThumbnailMode.CROP: True,
            ThumbnailMode.STRETCH: True,
        }[mode]

    if format is None:
        format = "jpg"
    if format not in THUMBNAIL_FORMATS:
        raise ValueError('Invalid thumbnail format "%s"' % format)

    if quality is not None and format != "jpg":
        raise ValueError(
            "The quality parameter is only supported for jpeg images")

    if seek < timedelta(0):
        raise ValueError("Seek must not be negative")

    ffmpeg = locate_executable("ffmpeg")
    if ffmpeg is None:
        raise RuntimeError("Failed to locate ffmpeg")
    info = get_video_info(source_video)

    source_dim = Dimensions(info["width"], info["height"])
    resize_dim, crop_dim = source_dim.resize(width, height, mode, upscale)

    # Construct a filename suffix unique to the given parameters
    suffix = get_suffix(seek, width, height, mode=mode, quality=quality)
    dst_url_path = get_dependent_url(source_url_path,
                                     suffix,
                                     ext=".{}".format(format))

    if quality is None and format == "jpg":
        quality = 95

    def build_thumbnail_artifact(artifact):
        artifact.ensure_dir()

        vfilter = "thumbnail,scale={rw}:{rh},crop={tw}:{th}".format(
            rw=resize_dim.width,
            rh=resize_dim.height,
            tw=crop_dim.width,
            th=crop_dim.height,
        )

        cmdline = [
            ffmpeg,
            "-loglevel",
            "-8",
            "-ss",
            get_timecode(seek),  # Input seeking since it's faster
            "-i",
            source_video,
            "-vf",
            vfilter,
            "-frames:v",
            "1",
            "-qscale:v",
            str(get_ffmpeg_quality(quality)),
            artifact.dst_filename,
        ]

        reporter.report_debug_info("ffmpeg cmd line", cmdline)
        proc = portable_popen(cmdline)
        if proc.wait() != 0:
            raise RuntimeError("ffmpeg exited with code {}".format(
                proc.returncode))

        if not os.path.exists(artifact.dst_filename):
            msg = ("Unable to create video thumbnail for {!r}. Maybe the seek "
                   "is outside of the video duration?")
            raise RuntimeError(msg.format(source_video))

    ctx.sub_artifact(artifact_name=dst_url_path,
                     sources=[source_video])(build_thumbnail_artifact)

    return Thumbnail(dst_url_path, crop_dim.width, crop_dim.height)
Esempio n. 29
0
 def parse_templates(self, to_filename):
     pybabel=locate_executable('pybabel')
     cmdline=[pybabel, 'extract', '-F', 'babel.cfg', "-o", to_filename, "./"]
     reporter.report_debug_info('pybabel cmd line', cmdline)
     portable_popen(cmdline).wait()
Esempio n. 30
0
 def _msg_init(self):
     """Generates the first <language>.po file"""
     msginit=locate_executable('msginit')
     cmdline=[msginit, "-i", "contents.pot", "-l", self.language, "-o", self.FILENAME_PATTERN%self.language, "--no-translator"]
     reporter.report_debug_info('msginit cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 31
0
 def _msg_merge(self):
     """Merges an existing <language>.po file with .pot file"""
     msgmerge=locate_executable('msgmerge')
     cmdline=[msgmerge, self.FILENAME_PATTERN%self.language, "contents.pot", "-U", "-N", "--backup=simple"]
     reporter.report_debug_info('msgmerge cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 32
0
 def _msg_fmt(self, locale_dirname):
     """Compile an existing <language>.po file into a .mo file"""
     msgfmt=locate_executable('msgfmt')
     cmdline=[msgfmt, self.FILENAME_PATTERN%self.language, "-o", join(locale_dirname,"contents.mo")]
     reporter.report_debug_info('msgfmt cmd line', cmdline)
     portable_popen(cmdline, cwd=self.i18npath).wait()
Esempio n. 33
0
import os
from datetime import timedelta

import pytest
from lektor.utils import locate_executable
from lektor.videotools import Dimensions, get_ffmpeg_quality, get_timecode

has_ffmpeg = locate_executable('ffmpeg')
has_ffprobe = locate_executable('ffprobe')
require_ffmpeg = pytest.mark.skipif(
    not has_ffmpeg or not has_ffprobe,
    reason='requires ffmpeg and ffprobe in path')


@pytest.mark.parametrize("td, tc", [
    (timedelta(), "00:00:00"),
    (timedelta(seconds=1), "00:00:01"),
    (timedelta(seconds=1.5), "00:00:01.5"),
    (timedelta(hours=8, minutes=15), "08:15:00"),
    (timedelta(hours=36, minutes=35, seconds=34.25), "36:35:34.25"),
])
def test_get_timecode(td, tc):
    assert get_timecode(td) == tc


@pytest.mark.parametrize("in_quality, out_quality", [
    (0, 31),
    (100, 2),
])
def test_get_ffmpeg_quality(in_quality, out_quality):
    assert get_ffmpeg_quality(in_quality) == out_quality