Merge branch 'master' into release

This commit is contained in:
Jamie Hardt
2022-11-18 22:49:45 -08:00
24 changed files with 176 additions and 141 deletions

40
.github/workflows/python-package.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Lint and Test
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4.3.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest

26
.github/workflows/pythonpublish.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Upload Python Package
on:
release:
types: [created]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_APIKEY }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*

11
.gitignore vendored
View File

@@ -10,10 +10,13 @@
# Vim Swapfiles
*.swp
.DS_Store
venv/
.coverage
lcov.info
# venv
venv/
.DS_Store
.coverage
lcov.info

View File

@@ -1,8 +0,0 @@
language: python
python:
- "3.6"
- "3.5"
script:
- "python3 setup.py test"
install:
- "pip3 install setuptools"

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
# Contributing
Contributions to this project are welcome!
The best way to contribute code to this project is to find this project on [Github][github] and submit a pull request.
## Call for EDLs
If you have EDLs you are having trouble working with becuase of unusual formatting, please send me a copy! Contact us
through [Github].
[github]: https://github.com/iluvcapra/pycmx

View File

@@ -1,4 +1,4 @@
Copyright (c) 2018 Jamie Hardt.
Copyright (c) 2022 Jamie Hardt.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.com/iluvcapra/pycmx.svg?branch=master)](https://travis-ci.com/iluvcapra/pycmx)
[![Documentation Status](https://readthedocs.org/projects/pycmx/badge/?version=latest)](https://pycmx.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/pycmx.svg) ![](https://img.shields.io/pypi/pyversions/pycmx.svg) [![](https://img.shields.io/pypi/v/pycmx.svg)](https://pypi.org/project/pycmx/) ![](https://img.shields.io/pypi/wheel/pycmx.svg)
![GitHub last commit](https://img.shields.io/github/last-commit/iluvcapra/pycmx)
[![Lint and Test](https://github.com/iluvcapra/pycmx/actions/workflows/python-package.yml/badge.svg)](https://github.com/iluvcapra/pycmx/actions/workflows/python-package.yml)
# pycmx
@@ -83,10 +84,4 @@ Audio channel 7 is present
False
```
## Should I Use This?
At this time, this is (at best) beta software. I feel like the interface is
about where where I'd like it to be but more testing is required.
Contributions are welcome and will make this module production-ready all the
faster! Please reach out or file a ticket!

Binary file not shown.

View File

@@ -1,35 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

24
docs/source/classes.rst Normal file
View File

@@ -0,0 +1,24 @@
pycmx Classes
=============
.. autoclass:: pycmx.edit_list.EditList
:members:
.. autoclass:: pycmx.event.Event
:members:
.. autoclass:: pycmx.edit.Edit
:members:
.. autoclass:: pycmx.transition.Transition
:members:
.. autoclass:: pycmx.channel_map.ChannelMap
:members:

View File

@@ -14,13 +14,13 @@
#
import os
import sys
sys.path.insert(0, os.path.abspath('../../pycmx'))
sys.path.insert(0, os.path.abspath('../..'))
print(sys.path)
# -- Project information -----------------------------------------------------
project = u'pycmx'
copyright = u'2018, Jamie Hardt'
copyright = u'2022, Jamie Hardt'
author = u'Jamie Hardt'
# The short X.Y version
@@ -63,7 +63,7 @@ master_doc = 'index'
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'em'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.

7
docs/source/function.rst Normal file
View File

@@ -0,0 +1,7 @@
Parse Function
==============
.. autofunction:: pycmx.parse_cmx_events.parse_cmx3600

View File

@@ -8,13 +8,13 @@ Welcome to pycmx's documentation!
.. toctree::
:maxdepth: 5
:caption: API Reference:
pycmx
:caption: API Reference
function
classes
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -1,7 +0,0 @@
pycmx
=====
.. toctree::
:maxdepth: 4
pycmx

View File

@@ -1,46 +0,0 @@
pycmx package
=============
Submodules
----------
pycmx.channel\_map module
-------------------------
.. automodule:: pycmx.channel_map
:members:
:undoc-members:
:show-inheritance:
pycmx.parse\_cmx\_events module
-------------------------------
.. automodule:: pycmx.parse_cmx_events
:members:
:undoc-members:
:show-inheritance:
pycmx.parse\_cmx\_statements module
-----------------------------------
.. automodule:: pycmx.parse_cmx_statements
:members:
:undoc-members:
:show-inheritance:
pycmx.util module
-----------------
.. automodule:: pycmx.util
:members:
:undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: pycmx
:members:
:undoc-members:
:show-inheritance:

View File

@@ -8,7 +8,7 @@ copy and reuse this software, refer to the LICENSE file included with the
distribution.
"""
__version__ = '1.0'
__version__ = '1.1.1'
__author__ = 'Jamie Hardt'
from .parse_cmx_events import parse_cmx3600

View File

@@ -2,13 +2,14 @@
# (c) 2018 Jamie Hardt
from re import (compile, match)
from typing import Dict, Tuple
class ChannelMap:
"""
Represents a set of all the channels to which an event applies.
"""
_chan_map = {
_chan_map : Dict[str, Tuple] = {
"V" : (True, False, False),
"A" : (False, True, False),
"A2" : (False, False, True),
@@ -27,6 +28,11 @@ class ChannelMap:
'True if video is included'
return self.v
@property
def audio(self):
'True if an audio channel is included'
return len(self._audio_channel_set) > 0
@property
def channels(self):
'A generator for each audio channel'
@@ -35,7 +41,7 @@ class ChannelMap:
@property
def a1(self):
"""True if A1 is included."""
"""True if A1 is included"""
return self.get_audio_channel(1)
@a1.setter
@@ -44,7 +50,7 @@ class ChannelMap:
@property
def a2(self):
"""True if A2 is included."""
"""True if A2 is included"""
return self.get_audio_channel(2)
@a2.setter
@@ -53,7 +59,7 @@ class ChannelMap:
@property
def a3(self):
"""True if A3 is included."""
"""True if A3 is included"""
return self.get_audio_channel(3)
@a3.setter
@@ -62,7 +68,7 @@ class ChannelMap:
@property
def a4(self):
"""True if A4 is included."""
"""True if A4 is included"""
return self.get_audio_channel(4)
@a4.setter
@@ -70,18 +76,18 @@ class ChannelMap:
self.set_audio_channel(4,val)
def get_audio_channel(self,chan_num):
"""True if chan_num is included."""
"""True if chan_num is included"""
return (chan_num in self._audio_channel_set)
def set_audio_channel(self,chan_num,enabled):
"""If enabled is true, chan_num will be included."""
"""If enabled is true, chan_num will be included"""
if enabled:
self._audio_channel_set.add(chan_num)
elif self.get_audio_channel(chan_num):
self._audio_channel_set.remove(chan_num)
def _append_event(self, event_str):
alt_channel_re = compile('^A(\d+)')
alt_channel_re = compile(r'^A(\d+)')
if event_str in self._chan_map:
channels = self._chan_map[event_str]
self.v = channels[0]
@@ -93,14 +99,15 @@ class ChannelMap:
self.set_audio_channel(int( matchresult.group(1)), True )
def _append_ext(self, audio_ext):
self.a3 = ext.audio3
self.a4 = ext.audio4
self.a3 = audio_ext.audio3
self.a4 = audio_ext.audio4
def __or__(self, other):
"""
Return the logical union of this channel map with another
the logical union of this channel map with another
"""
out_v = self.video | other.video
out_a = self._audio_channel_set | other._audio_channel_set
return ChannelMap(v=out_v,audio_channels = out_a)

View File

@@ -53,10 +53,8 @@ class EditList:
@property
def title(self):
"""
The title of this edit list, as attensted by the 'TITLE:' statement on
the first line.
The title of this edit list.
"""
'The title of the edit list'
return self.title_statement.title

View File

@@ -14,7 +14,7 @@ def parse_cmx3600(f):
f : a file-like object, anything that's readlines-able.
Returns:
An :class:`EditList`.
An :class:`pycmx.edit_list.EditList`.
"""
statements = parse_cmx3600_statements(f)
return EditList(statements)

View File

@@ -70,12 +70,12 @@ class Transition:
@property
def key_background(self):
"`True` if this edit is a key background."
return self.transition == KeyBackground
return self.transition == Transition.KeyBackground
@property
def key_foreground(self):
"`True` if this edit is a key foreground."
return self.transition == Key
return self.transition == Transition.Key
@property
def key_out(self):
@@ -83,4 +83,4 @@ class Transition:
`True` if this edit is a key out. This material will removed from
the key foreground and replaced with the key background.
"""
return self.transition == KeyOut
return self.transition == Transition.KeyOut

View File

@@ -1,2 +0,0 @@
#!/bin/bash
python3 -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*

9
requirements.txt Normal file
View File

@@ -0,0 +1,9 @@
attrs==22.1.0
coverage==6.5.0
exceptiongroup==1.0.4
iniconfig==1.1.1
packaging==21.3
pluggy==1.0.0
pyparsing==3.0.9
pytest==7.2.0
tomli==2.0.1

View File

@@ -4,20 +4,30 @@ with open("README.md", "r") as fh:
long_description = fh.read()
setup(name='pycmx',
version='1.0',
version='1.1.4',
author='Jamie Hardt',
author_email='jamiehardt@me.com',
description='CMX 3600 Edit Decision List Parser',
long_description_content_type="text/markdown",
long_description=long_description,
project_urls={
'Source':
'https://github.com/iluvcapra/pycmx',
'Documentation':
'https://pycmx.readthedocs.io/',
'Issues':
'https://github.com/iluvcapra/pycmx/issues',
},
url='https://github.com/iluvcapra/pycmx',
classifiers=['Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License',
'Topic :: Multimedia',
'Topic :: Multimedia :: Video',
'Topic :: Text Processing',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6'
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10'
],
packages=['pycmx'])

View File

@@ -66,6 +66,7 @@ class TestParse(TestCase):
self.assertFalse( events[0].edits[0].channels.a1)
self.assertTrue( events[0].edits[0].channels.a2)
self.assertTrue( events[2].edits[0].channels.get_audio_channel(7) )
self.assertTrue( events[2].edits[0].channels.audio)
def test_multi_edit_events(self):