New Upstream Release - guessit
Ready changes
Summary
Merged new upstream version: 3.7.1 (was: 3.5.0).
Diff
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9bf0b97..12b0586 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,33 +11,33 @@ jobs:
strategy:
matrix:
- python-version: [ "3.6", "3.7", "3.8", "3.9", "3.10" ] # pypy-3.6, pypy-3.7 are supported but a bit slow.
+ python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8", "pypy-3.9" ]
regex: [ "0", "1" ]
exclude:
# regex module doesn't play well with pypy and unicode.
- - python-version: "pypy-3.6"
+ - python-version: "pypy-3.8"
regex: "1"
- - python-version: "pypy-3.7"
+ - python-version: "pypy-3.9"
regex: "1"
# test regex module only with Python 3.9.
- - python-version: "3.6"
- regex: "1"
- python-version: "3.7"
regex: "1"
- python-version: "3.8"
regex: "1"
- python-version: "3.10"
regex: "1"
+ - python-version: "3.11"
+ regex: "1"
steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
- name: Setup python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- - name: Checkout
- uses: actions/checkout@v2
-
- name: Install Dependencies
run: |
pip install -e .[dev,test]
@@ -57,7 +57,7 @@ jobs:
REBULK_REGEX_ENABLED: ${{ matrix.regex }}
- name: Codecov
- uses: codecov/codecov-action@v1
+ uses: codecov/codecov-action@v3
commitlint:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
@@ -65,10 +65,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
fetch-depth: 0
- - uses: wagoid/commitlint-github-action@v2
+
+ - uses: wagoid/commitlint-github-action@v5
build-setuptools:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
@@ -77,16 +78,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Setup python 3.9
- uses: actions/setup-python@v2
- with:
- python-version: 3.9
-
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
+ - name: Setup python 3.9
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+
- name: Install Dependencies
run: |
pip install -e .[dev]
@@ -102,7 +103,7 @@ jobs:
- name: Build
run: python setup.py sdist bdist_wheel
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: guessit-python
path: ./dist
@@ -114,16 +115,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Setup python 3.9
- uses: actions/setup-python@v2
- with:
- python-version: 3.9
-
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
+ - name: Setup python 3.9
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+
- name: Install Dependencies
run: |
pip install -e .[dev]
@@ -142,7 +143,7 @@ jobs:
- name: Check binary
run: ./dist/guessit "Treme.1x03.Right.Place,.Wrong.Time.HDTV.XviD-NoTV.avi"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
if: matrix.regex == '0'
with:
name: guessit-bin-linux
@@ -155,16 +156,16 @@ jobs:
runs-on: windows-latest
steps:
- - name: Setup python 3.9
- uses: actions/setup-python@v2
- with:
- python-version: 3.9
-
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
+ - name: Setup python 3.9
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+
- name: Install Dependencies
run: |
pip install -e .[dev]
@@ -183,7 +184,7 @@ jobs:
- name: Check binary
run: ./dist/guessit "Treme.1x03.Right.Place,.Wrong.Time.HDTV.XviD-NoTV.avi"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: guessit-bin-windows
path: ./dist
@@ -195,16 +196,16 @@ jobs:
runs-on: macos-latest
steps:
- - name: Setup python 3.9
- uses: actions/setup-python@v2
- with:
- python-version: 3.9
-
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
+ - name: Setup python 3.9
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+
- name: Install Dependencies
run: |
pip install -e .[dev]
@@ -223,7 +224,7 @@ jobs:
- name: Check binary
run: ./dist/guessit "Treme.1x03.Right.Place,.Wrong.Time.HDTV.XviD-NoTV.avi"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: guessit-bin-macos
path: ./dist
@@ -235,17 +236,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Setup python 3.9
- uses: actions/setup-python@v2
- with:
- python-version: 3.9
-
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 0
- - uses: actions/download-artifact@v2
+ - name: Setup python 3.9
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.9
+
+ - uses: actions/download-artifact@v3
with:
path: artifacts
@@ -272,11 +273,11 @@ jobs:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
- name: Merge master to develop
- uses: robotology/gh-action-nightly-merge@v1.3.2
+ uses: robotology/gh-action-nightly-merge@v1.4.0
with:
stable_branch: 'master'
development_branch: 'develop'
allow_ff: true
user_name: github-actions
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/mkdocs.yml b/.github/workflows/mkdocs.yml
index d4cdcec..95f6161 100644
--- a/.github/workflows/mkdocs.yml
+++ b/.github/workflows/mkdocs.yml
@@ -7,8 +7,8 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
with:
python-version: 3.x
@@ -16,7 +16,7 @@ jobs:
- run: mkdocs build
- name: Deploy 🚀
- uses: JamesIves/github-pages-deploy-action@4.1.5
+ uses: JamesIves/github-pages-deploy-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d9f6b1d..f564c0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,37 @@ Changelog
<!--next-version-placeholder-->
+## v3.7.1 (2023-02-20)
+### Fix
+* **episode:** Ignore absolute_episode guess when SxxExx match is available in filepart ([`4aa5012`](https://github.com/guessit-io/guessit/commit/4aa5012edbf9f2898a417baec2c301859f5bcd92))
+* **title:** Fix title guessing for `Show Name/Season XX/episode.mkv` directories pattern ([`e717928`](https://github.com/guessit-io/guessit/commit/e717928b8544489bf8aa4f6b2866c0c10f3a7a88))
+
+## v3.7.0 (2023-02-18)
+### Feature
+* **week:** Add week property ([`8309bf1`](https://github.com/guessit-io/guessit/commit/8309bf14e34e17a871e0f496c27cf431aaba18e1))
+
+### Fix
+* **episode:** Fix invalid episode range when a weak episode is present before the match ([`ff0a327`](https://github.com/guessit-io/guessit/commit/ff0a3271af736f67e7a6a5fd12b92152035ea57b))
+* **expected:** Build output from input string for expected_title/expected_group ([`90cc215`](https://github.com/guessit-io/guessit/commit/90cc2156aafee39ef20c3cb3aaf0e26ddcb83933))
+* **release_group:** Properly extract group name from format "Title (MediaInfo Individual) [Group]" ([`25bd367`](https://github.com/guessit-io/guessit/commit/25bd367032262dc2a0ee06852c21846202413823))
+* **edition:** Improve remastered/restored detection ([`c3611b9`](https://github.com/guessit-io/guessit/commit/c3611b9b26e7f6c1b6bb2d0e9a708843f3242084))
+* **container:** Add m2ts to container extensions ([`05cca80`](https://github.com/guessit-io/guessit/commit/05cca806530302733377a278c4bb8c200b6a502c))
+
+### Documentation
+* **contributing:** Update branch name ([`4af631d`](https://github.com/guessit-io/guessit/commit/4af631df7a7945a7d229919d56c7f4d874750a4a))
+
+## v3.6.0 (2023-02-18)
+### Feature
+* **audio_codec:** Detect "DTS:X" (closes #728) ([`2bdd8f5`](https://github.com/guessit-io/guessit/commit/2bdd8f568a0fa6c5eb97e1f29d5e4d488d86a2aa))
+
+## v3.5.0 (2022-11-01)
+### Feature
+* **dependencies:** Drop Python 3.6 support ([`47f5718`](https://github.com/guessit-io/guessit/commit/47f57184a9d0a25c1b415638d0b003dad88ce607))
+
+### Fix
+* **audio_codec:** Detect "E-AC-3" and "AC-3" ([`72dc12e`](https://github.com/guessit-io/guessit/commit/72dc12e2489d240839a216041ffe47e9dd128b0f))
+* **typo:** Fix common typo ([`42a80f0`](https://github.com/guessit-io/guessit/commit/42a80f0992387c96fc120480aaea35e4b3d9f5b8))
+
## v3.4.3 (2021-11-20)
### Fix
* **setuptools:** Drop usage of test_requires and setup_requires ([#720](https://github.com/guessit-io/guessit/issues/720)) ([`324b38c`](https://github.com/guessit-io/guessit/commit/324b38ce62cd43efc51074dbd8c5e2ed64fc7573))
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 674716e..98dbd95 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,7 +8,7 @@ welcome!
for issues that should be ideal for people who are not very familiar
with the codebase yet.
2. Fork [the repository][] on Github to start making your changes to
- the **master** branch (or branch off of it).
+ the **develop** branch (or branch off of it).
3. Write a test which shows that the bug was fixed or that the feature
works as expected.
4. Send a pull request and bug the maintainer until it gets merged and
diff --git a/README.md b/README.md
index 2d313ee..002a834 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ For example, GuessIt can do the following:
"type": "episode"
}
-More information are available at [guessit.io](http://guessit.io/).
+More information is available at [guessit-io.github.io/guessit](https://guessit-io.github.io/guessit).
Support
-------
diff --git a/debian/changelog b/debian/changelog
index 2c9a176..432cd4f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+guessit (3.7.1-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Sun, 02 Apr 2023 13:00:43 -0000
+
guessit (3.4.3-2) unstable; urgency=medium
* Use secure URI in Homepage field.
diff --git a/docs/CNAME b/docs/CNAME
deleted file mode 100644
index 7af953d..0000000
--- a/docs/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-doc.guessit.io
\ No newline at end of file
diff --git a/docs/properties.md b/docs/properties.md
index 1142010..dc3f128 100644
--- a/docs/properties.md
+++ b/docs/properties.md
@@ -42,6 +42,10 @@ Main properties
Year of movie (or episode).
+- **week**
+
+ Week number, from 1 to 52, of episode.
+
- **release\_group**
Name of (non)scene group that released the file.
diff --git a/guessit/__version__.py b/guessit/__version__.py
index 2c2296b..24ac02e 100644
--- a/guessit/__version__.py
+++ b/guessit/__version__.py
@@ -4,4 +4,4 @@
Version module
"""
# pragma: no cover
-__version__ = '3.4.3'
+__version__ = '3.7.1'
diff --git a/guessit/api.py b/guessit/api.py
index 9b5e7f6..bc25b0d 100644
--- a/guessit/api.py
+++ b/guessit/api.py
@@ -23,7 +23,7 @@ class GuessitException(Exception):
"""
def __init__(self, string, options):
- super().__init__("An internal error has occured in guessit.\n"
+ super().__init__("An internal error has occurred in guessit.\n"
"===================== Guessit Exception Report =====================\n"
f"version={__version__}\n"
f"string={str(string)}\n"
@@ -98,7 +98,7 @@ def suggested_expected(titles, options=None):
return default_api.suggested_expected(titles, options)
-class GuessItApi(object):
+class GuessItApi:
"""
An api class that can be configured with custom Rebulk configuration.
"""
@@ -114,7 +114,7 @@ class GuessItApi(object):
"""
Reset api internal state.
"""
- self.__init__()
+ self.__init__() # pylint:disable=unnecessary-dunder-call
@classmethod
def _fix_encoding(cls, value):
diff --git a/guessit/config/options.json b/guessit/config/options.json
index 3539cf9..37b0df2 100644
--- a/guessit/config/options.json
+++ b/guessit/config/options.json
@@ -55,13 +55,14 @@
"audio_codec": {
"MP3": {"string": ["MP3", "LAME"],"regex": ["LAME(?:\\d)+-?(?:\\d)+"]},
"MP2": "MP2",
- "Dolby Digital": {"string": ["Dolby", "DolbyDigital"], "regex": ["Dolby-Digital", "DD", "AC3D?"]},
+ "Dolby Digital": {"string": ["Dolby", "DolbyDigital"], "regex": ["Dolby-Digital", "DD", "AC-?3D?"]},
"Dolby Atmos": {"string": ["Atmos"], "regex": ["Dolby-?Atmos"]},
"AAC": "AAC",
- "Dolby Digital Plus": ["EAC3", "DDP", "DD+"],
+ "Dolby Digital Plus": {"string": ["DDP", "DD+"], "regex": ["E-?AC-?3"]},
"FLAC": "Flac",
"DTS": "DTS",
"DTS-HD": {"regex": ["DTS-?HD", "DTS(?=-?MA)"], "conflict_solver": "lambda match, other: other if other.name == 'audio_codec' else '__default__'"},
+ "DTS:X": {"string": ["DTS:X", "DTS-X", "DTSX"] },
"Dolby TrueHD": {"regex": ["True-?HD"] },
"Opus": "Opus",
"Vorbis": "Vorbis",
@@ -189,6 +190,7 @@
"ram",
"rm",
"ts",
+ "m2ts",
"vob",
"wav",
"webm",
@@ -241,12 +243,10 @@
"Extended": {"string": ["extended"], "regex": ["extended-?cut", "extended-?version"], "tags": ["has-neighbor", "release-group-prefix"]},
"Alternative Cut": {"regex": ["alternat(e|ive)(?:-?Cut)?"], "tags": ["has-neighbor", "release-group-prefix"]},
"Remastered": [
- {"string": "Remastered", "tags": ["has-neighbor", "release-group-prefix"]},
- {"regex": "4k-remaster(?:ed)?", "tags": ["release-group-prefix"]}
+ {"regex": "(?:4k.)?remaster(?:ed)?", "tags": ["release-group-prefix"]}
],
"Restored": [
- {"string": "Restored", "tags": ["has-neighbor", "release-group-prefix"]},
- {"regex": "4k-restore(?:d)?", "tags": ["release-group-prefix"]}
+ {"regex": "(?:4k.)?restore(?:d)?", "tags": ["release-group-prefix"]}
],
"Uncensored": {"string": "Uncensored", "tags": ["has-neighbor", "release-group-prefix"]},
"Uncut": {"string": "Uncut", "tags": ["has-neighbor", "release-group-prefix"]},
@@ -839,6 +839,9 @@
"Yahoo": "YHOO",
"YouTube Red": "RED",
"ZDF": "ZDF"
+ },
+ "date": {
+ "week_words": ["week"]
}
}
}
diff --git a/guessit/rules/common/date.py b/guessit/rules/common/date.py
index 1e11456..5850e9d 100644
--- a/guessit/rules/common/date.py
+++ b/guessit/rules/common/date.py
@@ -34,6 +34,11 @@ def valid_year(year):
return 1920 <= year < 2030
+def valid_week(week):
+ """Check if number is a valid week"""
+ return 1 <= week < 53
+
+
def _is_int(string):
"""
Check if the input string is an integer
diff --git a/guessit/rules/common/expected.py b/guessit/rules/common/expected.py
index 19f2f88..000fcbf 100644
--- a/guessit/rules/common/expected.py
+++ b/guessit/rules/common/expected.py
@@ -3,9 +3,8 @@
"""
Expected property factory
"""
-from rebulk.remodule import re
-
from rebulk import Rebulk
+from rebulk.remodule import re
from rebulk.utils import find_all
from . import dash, seps
@@ -42,12 +41,13 @@ def build_expected_function(context_key):
for match in matches:
ret.append(match.span)
else:
- value = search
for sep in seps:
input_string = input_string.replace(sep, ' ')
search = search.replace(sep, ' ')
for start in find_all(input_string, search, ignore_case=True):
- ret.append({'start': start, 'end': start + len(search), 'value': value})
+ end = start + len(search)
+ value = input_string[start:end]
+ ret.append({'start': start, 'end': end, 'value': value})
return ret
return expected
diff --git a/guessit/rules/common/quantity.py b/guessit/rules/common/quantity.py
index 2a4fcdc..aed15e7 100644
--- a/guessit/rules/common/quantity.py
+++ b/guessit/rules/common/quantity.py
@@ -10,7 +10,7 @@ from rebulk.remodule import re
from ..common import seps
-class Quantity(object):
+class Quantity:
"""
Represent a quantity object with magnitude and units.
"""
diff --git a/guessit/rules/properties/cd.py b/guessit/rules/properties/cd.py
index f9b3424..6ede364 100644
--- a/guessit/rules/properties/cd.py
+++ b/guessit/rules/properties/cd.py
@@ -11,7 +11,7 @@ from ..common.pattern import is_disabled
from ...config import load_config_patterns
-def cd(config): # pylint:disable=unused-argument
+def cd(config): # pylint:disable=unused-argument,invalid-name
"""
Builder for rebulk object.
diff --git a/guessit/rules/properties/country.py b/guessit/rules/properties/country.py
index 69f8890..f115614 100644
--- a/guessit/rules/properties/country.py
+++ b/guessit/rules/properties/country.py
@@ -87,7 +87,7 @@ class GuessitCountryConverter(babelfish.CountryReverseConverter): # pylint: dis
raise babelfish.CountryReverseError(name)
-class CountryFinder(object):
+class CountryFinder:
"""Helper class to search and return country matches."""
def __init__(self, allowed_countries, common_words):
diff --git a/guessit/rules/properties/crc.py b/guessit/rules/properties/crc.py
index eedee93..d842157 100644
--- a/guessit/rules/properties/crc.py
+++ b/guessit/rules/properties/crc.py
@@ -35,9 +35,9 @@ def crc(config): # pylint:disable=unused-argument
return rebulk
-_DIGIT = 0
-_LETTER = 1
-_OTHER = 2
+_digit = 0
+_letter = 1
+_other = 2
_idnum = re.compile(r'(?P<uuid>[a-zA-Z0-9-]{20,})') # 1.0, (0, 0))
@@ -61,18 +61,18 @@ def guess_idnumber(string):
letter_count = 0
last_letter = None
- last = _LETTER
+ last = _letter
for c in result['uuid']:
if c in '0123456789':
- ci = _DIGIT
+ ci = _digit
elif c in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
- ci = _LETTER
+ ci = _letter
if c != last_letter:
switch_letter_count += 1
last_letter = c
letter_count += 1
else:
- ci = _OTHER
+ ci = _other
if ci != last:
switch_count += 1
diff --git a/guessit/rules/properties/date.py b/guessit/rules/properties/date.py
index e50cdfa..4f322c3 100644
--- a/guessit/rules/properties/date.py
+++ b/guessit/rules/properties/date.py
@@ -1,13 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
-date and year properties
+date, week and year properties
"""
+import re
+
from rebulk import Rebulk, RemoveMatch, Rule
-from ..common.date import search_date, valid_year
+from ..common import dash
+from ..common.date import search_date, valid_year, valid_week
from ..common.pattern import is_disabled
from ..common.validators import seps_surround
+from ...reutils import build_or_pattern
def date(config): # pylint:disable=unused-argument
@@ -28,6 +32,15 @@ def date(config): # pylint:disable=unused-argument
else '__default__',
validator=lambda match: seps_surround(match) and valid_year(match.value))
+ rebulk.regex(build_or_pattern(config.get('week_words')) + r"-?(\d{1,2})",
+ name="week", formatter=int,
+ children=True,
+ flags=re.IGNORECASE, abbreviations=[dash],
+ conflict_solver=lambda match, other: other
+ if other.name in ('episode', 'season') and len(other.raw) < len(match.raw)
+ else '__default__',
+ validator=lambda match: seps_surround(match) and valid_week(match.value))
+
def date_functional(string, context): # pylint:disable=inconsistent-return-statements
"""
Search for date in the string and retrieves match
diff --git a/guessit/rules/properties/episodes.py b/guessit/rules/properties/episodes.py
index 7aa2245..cbb05b8 100644
--- a/guessit/rules/properties/episodes.py
+++ b/guessit/rules/properties/episodes.py
@@ -68,8 +68,8 @@ def episodes(config):
if other.name in ('video_codec', 'audio_codec', 'container', 'date'):
return match
if (other.name == 'audio_channels' and 'weak-audio_channels' not in other.tags
- and not match.initiator.children.named(match.name + 'Marker')) or (
- other.name == 'screen_size' and not int_coercable(other.raw)):
+ and not match.initiator.children.named(match.name + 'Marker')) or (
+ other.name == 'screen_size' and not int_coercable(other.raw)):
return match
if other.name in ('season', 'episode') and match.initiator != other.initiator:
if (match.initiator.name in ('weak_episode', 'weak_duplicate')
@@ -172,7 +172,7 @@ def episodes(config):
disabled=is_season_episode_disabled) \
.defaults(tags=['SxxExx']) \
.regex(build_or_pattern(season_markers, name='seasonMarker') + r'(?P<season>\d+)@?' +
- build_or_pattern(episode_markers + disc_markers, name='episodeMarker') + r'@?(?P<episode>\d+)')\
+ build_or_pattern(episode_markers + disc_markers, name='episodeMarker') + r'@?(?P<episode>\d+)') \
.repeater('+') \
.regex(build_or_pattern(episode_markers + disc_markers + discrete_separators + range_separators,
name='episodeSeparator',
@@ -186,7 +186,7 @@ def episodes(config):
.defaults(tags=['SxxExx']) \
.regex(r'(?P<season>\d+)@?' +
build_or_pattern(season_ep_markers, name='episodeMarker') +
- r'@?(?P<episode>\d+)').repeater('+') \
+ r'@?(?P<episode>\d+)').repeater('+')
rebulk.chain(tags=['SxxExx'],
validate_all=True,
@@ -338,7 +338,6 @@ def episodes(config):
rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator'])
- # TODO: List of words
# detached of X count (season/episode)
rebulk.regex(r'(?P<episode>\d+)-?' + build_or_pattern(of_words) +
r'-?(?P<count>\d+)-?' + build_or_pattern(episode_words) + '?',
@@ -512,7 +511,6 @@ class AbstractSeparatorRange(Rule):
"""
Remove separator matches and create matches for season range.
"""
- priority = 128
consequence = [RemoveMatch, AppendMatch]
def __init__(self, range_separators, property_name):
@@ -520,6 +518,9 @@ class AbstractSeparatorRange(Rule):
self.range_separators = range_separators
self.property_name = property_name
+ def _can_start_range(self, match): # pylint: disable=unused-argument
+ return True
+
def when(self, matches, context):
to_remove = []
to_append = []
@@ -540,7 +541,10 @@ class AbstractSeparatorRange(Rule):
to_remove.append(separator)
previous_match = None
- for next_match in matches.named(self.property_name):
+ sorted_matches = sorted(matches.named(self.property_name), key=lambda x: x.span[0])
+ for next_match in sorted_matches:
+ if not previous_match and not self._can_start_range(next_match):
+ continue
if previous_match:
separator = matches.input_string[previous_match.initiator.end:next_match.initiator.start]
if separator not in self.range_separators:
@@ -578,17 +582,25 @@ class RenameToAbsoluteEpisode(Rule):
The matches in the group with higher episode values are renamed to absolute_episode.
"""
- consequence = RenameMatch('absolute_episode')
+ consequence = [RenameMatch('absolute_episode'), RemoveMatch]
def when(self, matches, context): # pylint:disable=inconsistent-return-statements
initiators = {match.initiator for match in matches.named('episode')
if len(match.initiator.children.named('episode')) > 1}
if len(initiators) != 2:
- ret = []
+ ret = ([], [])
for filepart in matches.markers.named('path'):
+ sxxexx_episode_matches = matches.range(filepart.start + 1, filepart.end,
+ predicate=lambda m: m.name == 'episode' and
+ 'SxxExx' in m.tags)
if matches.range(filepart.start + 1, filepart.end, predicate=lambda m: m.name == 'episode'):
- ret.extend(
- matches.starting(filepart.start, predicate=lambda m: m.initiator.name == 'weak_episode'))
+ absolute_episode_candidate = matches.starting(filepart.start,
+ predicate=lambda
+ m: m.initiator.name == 'weak_episode')
+ if sxxexx_episode_matches:
+ ret[1].extend(absolute_episode_candidate)
+ else:
+ ret[0].extend(absolute_episode_candidate)
return ret
initiators = sorted(initiators, key=lambda item: item.end)
@@ -597,24 +609,29 @@ class RenameToAbsoluteEpisode(Rule):
second_range = matches.named('episode', predicate=lambda m: m.initiator == initiators[1])
if len(first_range) == len(second_range):
if second_range[0].value > first_range[0].value:
- return second_range
+ return second_range, []
if first_range[0].value > second_range[0].value:
- return first_range
+ return first_range, []
class EpisodeNumberSeparatorRange(AbstractSeparatorRange):
"""
Remove separator matches and create matches for episoderNumber range.
"""
+ priority = 128
def __init__(self, range_separators):
super().__init__(range_separators, "episode")
+ def _can_start_range(self, match):
+ return 'weak-episode' not in match.tags
+
class SeasonSeparatorRange(AbstractSeparatorRange):
"""
Remove separator matches and create matches for season range.
"""
+ priority = 128
def __init__(self, range_separators):
super().__init__(range_separators, "season")
@@ -728,7 +745,7 @@ class RemoveInvalidSeason(Rule):
for filepart in matches.markers.named('path'):
strong_season = matches.range(filepart.start, filepart.end, index=0,
predicate=lambda m: m.name == 'season'
- and not m.private and 'SxxExx' in m.tags)
+ and not m.private and 'SxxExx' in m.tags)
if strong_season:
if strong_season.initiator.children.named('episode'):
for season in matches.range(strong_season.end, filepart.end,
@@ -756,7 +773,7 @@ class RemoveInvalidEpisode(Rule):
for filepart in matches.markers.named('path'):
strong_episode = matches.range(filepart.start, filepart.end, index=0,
predicate=lambda m: m.name == 'episode'
- and not m.private and 'SxxExx' in m.tags)
+ and not m.private and 'SxxExx' in m.tags)
if strong_episode:
strong_ep_marker = RemoveInvalidEpisode.get_episode_prefix(matches, strong_episode)
for episode in matches.range(strong_episode.end, filepart.end,
@@ -843,7 +860,7 @@ class RemoveDetachedEpisodeNumber(Rule):
episode_numbers[0].value < 10 and \
episode_numbers[1].value - episode_numbers[0].value != 1:
parent = episode_numbers[0]
- while parent: # TODO: Add a feature in rebulk to avoid this ...
+ while parent:
ret.append(parent)
parent = parent.parent
return ret
diff --git a/guessit/rules/properties/language.py b/guessit/rules/properties/language.py
index 8a83d88..3c41e10 100644
--- a/guessit/rules/properties/language.py
+++ b/guessit/rules/properties/language.py
@@ -137,7 +137,7 @@ def length_comparator(value):
_LanguageMatch = namedtuple('_LanguageMatch', ['property_name', 'word', 'lang'])
-class LanguageWord(object):
+class LanguageWord:
"""
Extension to the Word namedtuple in order to create compound words.
@@ -191,7 +191,7 @@ def to_rebulk_match(language_match):
}
-class LanguageFinder(object):
+class LanguageFinder:
"""
Helper class to search and return language matches: 'language' and 'subtitle_language' properties
"""
diff --git a/guessit/rules/properties/release_group.py b/guessit/rules/properties/release_group.py
index 09e845f..4f5286c 100644
--- a/guessit/rules/properties/release_group.py
+++ b/guessit/rules/properties/release_group.py
@@ -4,6 +4,7 @@
release_group property
"""
import copy
+import re
from rebulk import Rebulk, Rule, AppendMatch, RemoveMatch
from rebulk.match import Match
@@ -50,7 +51,10 @@ def release_group(config):
if string.lower().endswith(forbidden) and string[-len(forbidden) - 1:-len(forbidden)] in seps:
string = string[:len(forbidden)]
string = string.strip(groupname_seps)
- return string.strip()
+
+ # Release groups that credit individual members often use a format like "Title (MediaInfo Individual) [Group]".
+ # This results in a group name of "Individual) [Group]", which should be transformed to "Individual Group".
+ return re.sub(r'(.+)\)\s?\[(.+)\]', r'\1 \2', string.strip())
rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'release_group'))
diff --git a/guessit/rules/properties/title.py b/guessit/rules/properties/title.py
index 1d57de1..fad8484 100644
--- a/guessit/rules/properties/title.py
+++ b/guessit/rules/properties/title.py
@@ -49,7 +49,7 @@ class TitleBaseRule(Rule):
"""
Add title match in existing matches
"""
- # pylint:disable=no-self-use,unused-argument
+ # pylint:disable=unused-argument
consequence = [AppendMatch, RemoveMatch]
def __init__(self, match_name, match_tags=None, alternative_match_name=None):
@@ -142,8 +142,8 @@ class TitleBaseRule(Rule):
for outside in outside_matches:
other_languages.extend(matches.range(outside.start, outside.end,
lambda c_match: c_match.name == match.name and
- c_match not in to_keep and
- c_match.value not in NON_SPECIFIC_LANGUAGES))
+ c_match not in to_keep and
+ c_match.value not in NON_SPECIFIC_LANGUAGES))
if not other_languages and (not starting or len(match.raw) <= 3):
return True
@@ -163,7 +163,8 @@ class TitleBaseRule(Rule):
return match.start >= hole.start and match.end <= hole.end
return True
- def check_titles_in_filepart(self, filepart, matches, context): # pylint:disable=inconsistent-return-statements
+ def check_titles_in_filepart(self, filepart, matches, context, # pylint:disable=inconsistent-return-statements
+ additional_ignored=None):
"""
Find title in filepart (ignoring language)
"""
@@ -171,7 +172,8 @@ class TitleBaseRule(Rule):
start, end = filepart.span
holes = matches.holes(start, end + 1, formatter=formatters(cleanup, reorder_title),
- ignore=self.is_ignored,
+ ignore=self.is_ignored if additional_ignored is None else lambda m: self.is_ignored(
+ m) or additional_ignored(m),
predicate=lambda m: m.value)
holes = self.holes_process(holes, matches)
@@ -247,8 +249,46 @@ class TitleBaseRule(Rule):
titles = [hole]
return titles, to_remove
+ def _serie_name_filepart(self, matches, fileparts):
+ # Try to get show title from subdirectory of a season only directory (Show Name/Season 1/episode_title.avi)
+ for index in range(len(fileparts) - 1):
+ if index == 0:
+ continue
+ filepart = fileparts[index]
+ filepart_matches = [m for m in matches.range(filepart.start, filepart.end) if not m.private]
+ if len(filepart_matches) == 1 and filepart_matches[0].name == 'season' and \
+ (filepart_matches[0].span == filepart.span or
+ filepart_matches[0].parent and filepart_matches[0].parent.span == filepart.span):
+ # Filepath match season match exactly
+ return fileparts[index + 1]
+ return None
+
+ def _serie_name_filepart_match(self, matches, context, serie_name_filepart, to_append, to_remove):
+ def serie_name_filepart_ignored(match):
+ for tag in match.tags:
+ if tag == 'weak' or tag.startswith('weak-'):
+ return True
+ return False
+
+ titles = self.check_titles_in_filepart(serie_name_filepart, matches, context, serie_name_filepart_ignored)
+ if titles:
+ titles, to_remove_c = titles
+ if len(titles) == 1:
+ to_append.extend(titles)
+ to_remove.extend(to_remove_c)
+ return titles[0]
+ return None
+
+ def _year_fileparts(self, matches, fileparts):
+ year_fileparts = []
+ for filepart in fileparts:
+ year_match = matches.range(filepart.start, filepart.end, lambda match: match.name == 'year', 0)
+ if year_match:
+ year_fileparts.append(filepart)
+ return year_fileparts
+
def when(self, matches, context):
- ret = []
+ to_append = []
to_remove = []
if matches.named(self.match_name, lambda match: 'expected' in match.tags):
@@ -257,36 +297,43 @@ class TitleBaseRule(Rule):
fileparts = [filepart for filepart in list(marker_sorted(matches.markers.named('path'), matches))
if not self.filepart_filter or self.filepart_filter(filepart, matches)]
- # Priorize fileparts containing the year
- years_fileparts = []
- for filepart in fileparts:
- year_match = matches.range(filepart.start, filepart.end, lambda match: match.name == 'year', 0)
- if year_match:
- years_fileparts.append(filepart)
+ serie_name_filepart = self._serie_name_filepart(matches, fileparts)
+
+ serie_name_filepath_match = None
+ if serie_name_filepart:
+ serie_name_filepath_match = self._serie_name_filepart_match(matches, context, serie_name_filepart,
+ to_append, to_remove)
+
+ # Force inclusion of fileparts containing the year
+ year_fileparts = self._year_fileparts(matches, fileparts)
for filepart in fileparts:
try:
- years_fileparts.remove(filepart)
+ year_fileparts.remove(filepart)
except ValueError:
pass
titles = self.check_titles_in_filepart(filepart, matches, context)
if titles:
titles, to_remove_c = titles
- ret.extend(titles)
+ if serie_name_filepath_match:
+ for title_match in titles:
+ if title_match.value != serie_name_filepath_match.value:
+ title_match.name = 'episode_title'
+ to_append.extend(titles)
to_remove.extend(to_remove_c)
break
# Add title match in all fileparts containing the year.
- for filepart in years_fileparts:
+ for filepart in year_fileparts:
titles = self.check_titles_in_filepart(filepart, matches, context)
if titles:
# pylint:disable=unbalanced-tuple-unpacking
titles, to_remove_c = titles
- ret.extend(titles)
+ to_append.extend(titles)
to_remove.extend(to_remove_c)
- if ret or to_remove:
- return ret, to_remove
+ if to_append or to_remove:
+ return to_append, to_remove
return False
diff --git a/guessit/test/__init__.py b/guessit/test/__init__.py
index e5be370..c5db3ab 100644
--- a/guessit/test/__init__.py
+++ b/guessit/test/__init__.py
@@ -1,3 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name
+# pylint: disable=pointless-statement, missing-docstring, invalid-name
diff --git a/guessit/test/episodes.yml b/guessit/test/episodes.yml
index 52e29ec..7de7da1 100644
--- a/guessit/test/episodes.yml
+++ b/guessit/test/episodes.yml
@@ -2340,7 +2340,7 @@
? /11.22.63/Season 1/11.22.63.106.hdtv-abc
: options: -T 11.22.63
- title: 11.22.63
+ title: 11 22 63
season: 1
episode: 6
source: HDTV
@@ -4062,8 +4062,7 @@
type: episode
? 165.Show Name.s08e014
-: absolute_episode: 165
- title: Show Name
+: title: 165 Show Name
season: 8
episode: 14
type: episode
@@ -4672,7 +4671,7 @@
episode: 1
screen_size: 1080p
streaming_service: Viki
- source: Web
+ source: Web
release_group: BLUEBERRY
container: mp4
mimetype: video/mp4
@@ -4702,7 +4701,6 @@
video_codec: H.264
audio_codec: FLAC
container: mkv
- mimetype: video/x-matroska
type: episode
? "[EveTaku] Kyouso Giga ONA v2 [540p][128BAC43].mkv"
@@ -4713,7 +4711,6 @@
screen_size: 540p
crc32: 128BAC43
container: mkv
- mimetype: video/x-matroska
type: episode
? '[Erai-raws] Fumetsu no Anata e - 03 [720p][Multiple Subtitle].mkv'
@@ -4723,7 +4720,6 @@
screen_size: 720p
subtitle_language: mul
container: mkv
- mimetype: video/x-matroska
type: episode
? Mom.S06E08.Jell-O.Shots.and.the.Truth.About.Santa.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTb.mkv
@@ -4739,7 +4735,6 @@
video_codec: H.264
release_group: NTb
container: mkv
- mimetype: video/x-matroska
type: episode
? Archer.2009.S12E05.Shots.720p.HULU.WEB-DL.DDP5.1.H.264-NOGRP
@@ -4756,3 +4751,22 @@
video_codec: H.264
release_group: NOGRP
type: episode
+
+? /mydatapool/mydata/Videos/Shows/C/Caprica (2008)/Season 1/Apotheosis_1920x1080.mp4
+: title: Caprica
+ year: 2008
+ season: 1
+ episode_title: Apotheosis
+ screen_size: 1080p
+ container: mp4
+ type: episode
+
+? 4400.S01E01.1080p.WEB.H264-NOGRP
+: title: '4400'
+ season: 1
+ episode: 1
+ screen_size: 1080p
+ source: Web
+ video_codec: H.264
+ release_group: NOGRP
+ type: episode
diff --git a/guessit/test/movies.yml b/guessit/test/movies.yml
index ff4232a..9fce923 100644
--- a/guessit/test/movies.yml
+++ b/guessit/test/movies.yml
@@ -1711,6 +1711,20 @@
release_group: LAZY
type: movie
+? The.Movie.2016.2160p.UHD.BluRay.REMUX.HDR.HEVC.DTS-X-NOGROUP
+: title: The Movie
+ year: 2016
+ screen_size: 2160p
+ source: Ultra HD Blu-ray
+ other:
+ - HDR10
+ - Remux
+ video_codec: H.265
+ video_profile: High Efficiency Video Coding
+ audio_codec: DTS:X
+ release_group: NOGROUP
+ type: movie
+
? Test (2013) [WEBDL-1080p] [x264 AC3] [ENG+RU+PT] [NTb].mkv
: title: Test
year: 2013
@@ -1857,5 +1871,4 @@
video_codec: H.264
release_group: DON
container: mkv
- mimetype: video/x-matroska
type: movie
diff --git a/guessit/test/rules/__init__.py b/guessit/test/rules/__init__.py
index e5be370..c5db3ab 100644
--- a/guessit/test/rules/__init__.py
+++ b/guessit/test/rules/__init__.py
@@ -1,3 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name
+# pylint: disable=pointless-statement, missing-docstring, invalid-name
diff --git a/guessit/test/rules/audio_codec.yml b/guessit/test/rules/audio_codec.yml
index 1c78efc..b215751 100644
--- a/guessit/test/rules/audio_codec.yml
+++ b/guessit/test/rules/audio_codec.yml
@@ -15,11 +15,15 @@
? +DD
? +Dolby Digital
? +AC3
+? +AC-3
: audio_codec: Dolby Digital
? +DDP
? +DD+
? +EAC3
+? +EAC-3
+? +E-AC-3
+? +E-AC3
: audio_codec: Dolby Digital Plus
? +DolbyAtmos
@@ -116,6 +120,11 @@
: audio_codec: DTS
audio_profile: Extended Surround
+? DTS:X
+? DTS-X
+? DTSX
+: audio_codec: DTS:X
+
? DD-EX
? DDEX
? -EX
diff --git a/guessit/test/rules/edition.yml b/guessit/test/rules/edition.yml
index d1d5277..c34d606 100644
--- a/guessit/test/rules/edition.yml
+++ b/guessit/test/rules/edition.yml
@@ -31,6 +31,22 @@
? Super Movie Alternative Cut XViD
: edition: Alternative Cut
+? Remaster
+? Remastered
+? 4k-Remaster
+? 4k-Remastered
+? 4k Remaster
+? 4k Remastered
+: edition: Remastered
+
+? Restore
+? Restored
+? 4k-Restore
+? 4k-Restored
+? 4k Restore
+? 4k Restored
+: edition: Restored
+
? ddc
: edition: Director's Definitive Cut
diff --git a/guessit/test/rules/episodes.yml b/guessit/test/rules/episodes.yml
index 44e06a3..7eff1e7 100644
--- a/guessit/test/rules/episodes.yml
+++ b/guessit/test/rules/episodes.yml
@@ -293,7 +293,7 @@
? Something 4x05-06
? Something-4x05-06
: options: -T something
- title: something
+ title: Something
season: 4
episode:
- 5
@@ -329,3 +329,15 @@
year: 2010
season: 2010
episode: 2
+
+? Show Name - S32-Dummy 45-Ep 6478
+: title: Show Name
+ episode_title: Dummy 45
+ season: 32
+ episode: 6478
+
+? Show Name - S32-Week 45-Ep 6478
+: title: Show Name
+ season: 32
+ week: 45
+ episode: 6478
diff --git a/guessit/test/rules/processors_test.py b/guessit/test/rules/processors_test.py
index c22e968..57f04be 100644
--- a/guessit/test/rules/processors_test.py
+++ b/guessit/test/rules/processors_test.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, pointless-string-statement
+# pylint: disable=pointless-statement, missing-docstring, invalid-name, pointless-string-statement
from rebulk.match import Matches, Match
diff --git a/guessit/test/rules/release_group.yml b/guessit/test/rules/release_group.yml
index c96383e..53e5f73 100644
--- a/guessit/test/rules/release_group.yml
+++ b/guessit/test/rules/release_group.yml
@@ -69,3 +69,12 @@
: title: Show Name
video_codec: H.264
release_group: RiPRG
+
+? Archer (2009) S13E01 The Big Con (1080p AMZN Webrip x265 10bit EAC3 5.1 - JBENT)[TAoE]
+: release_group: JBENT TAoE
+
+? Dark Phoenix (2019) (1080p BluRay x265 HEVC 10bit AAC 7.1 Tigole) [QxR]
+: release_group: Tigole QxR
+
+? The Peripheral (2022) Season 1 S01 (1080p AMZN WEB-DL x265 HEVC 10bit DDP5.1 D0ct0rLew) [SEV]
+: release_group: D0ct0rLew SEV
\ No newline at end of file
diff --git a/guessit/test/rules/title.yml b/guessit/test/rules/title.yml
index 05c7f20..82bd91b 100644
--- a/guessit/test/rules/title.yml
+++ b/guessit/test/rules/title.yml
@@ -41,3 +41,8 @@
episode_title: This E.P.T.I.T.L.E has dots
type: episode
+? /mydatapool/mydata/Videos/Shows/C/Caprica/Season 1/Apotheosis_1920x1080.mp4
+: title: Caprica
+ episode_title: Apotheosis
+ season: 1
+ type: episode
diff --git a/guessit/test/test_api.py b/guessit/test/test_api.py
index 790de20..e559834 100644
--- a/guessit/test/test_api.py
+++ b/guessit/test/test_api.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, pointless-string-statement
+# pylint: disable=pointless-statement, missing-docstring, invalid-name, pointless-string-statement
import json
import os
from pathlib import Path
@@ -58,7 +58,7 @@ def test_properties():
def test_exception():
with pytest.raises(GuessitException) as excinfo:
guessit(object())
- assert "An internal error has occured in guessit" in str(excinfo.value)
+ assert "An internal error has occurred in guessit" in str(excinfo.value)
assert "Guessit Exception Report" in str(excinfo.value)
assert "Please report at https://github.com/guessit-io/guessit/issues" in str(excinfo.value)
diff --git a/guessit/test/test_api_unicode_literals.py b/guessit/test/test_api_unicode_literals.py
index 79bbbca..fa6227d 100644
--- a/guessit/test/test_api_unicode_literals.py
+++ b/guessit/test/test_api_unicode_literals.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, pointless-string-statement
+# pylint: disable=pointless-statement, missing-docstring, invalid-name, pointless-string-statement
import os
@@ -60,6 +60,6 @@ def test_properties():
def test_exception():
with pytest.raises(GuessitException) as excinfo:
guessit(object())
- assert "An internal error has occured in guessit" in str(excinfo.value)
+ assert "An internal error has occurred in guessit" in str(excinfo.value)
assert "Guessit Exception Report" in str(excinfo.value)
assert "Please report at https://github.com/guessit-io/guessit/issues" in str(excinfo.value)
diff --git a/guessit/test/test_benchmark.py b/guessit/test/test_benchmark.py
index 34386e3..0c561ee 100644
--- a/guessit/test/test_benchmark.py
+++ b/guessit/test/test_benchmark.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use,pointless-statement,missing-docstring,invalid-name,line-too-long
+# pylint: disable=pointless-statement,missing-docstring,invalid-name,line-too-long
import time
import pytest
@@ -34,7 +34,7 @@ def case4():
warmup=False
)
@pytest.mark.skipif(True, reason="Disabled")
-class TestBenchmark(object):
+class TestBenchmark:
def test_case1(self, benchmark):
ret = benchmark(case1)
assert ret
diff --git a/guessit/test/test_main.py b/guessit/test/test_main.py
index a34cd4a..90b8169 100644
--- a/guessit/test/test_main.py
+++ b/guessit/test/test_main.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name
+# pylint: disable=pointless-statement, missing-docstring, invalid-name
import json
import os
import sys
diff --git a/guessit/test/test_options.py b/guessit/test/test_options.py
index 4f019b3..de13180 100644
--- a/guessit/test/test_options.py
+++ b/guessit/test/test_options.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, pointless-string-statement
+# pylint: disable=pointless-statement, missing-docstring, invalid-name, pointless-string-statement
import os
import pytest
diff --git a/guessit/test/test_yml.py b/guessit/test/test_yml.py
index 53d7f67..6adced1 100644
--- a/guessit/test/test_yml.py
+++ b/guessit/test/test_yml.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name
+# pylint: disable=pointless-statement, missing-docstring, invalid-name
import logging
import os
@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
-class EntryResult(object):
+class EntryResult:
def __init__(self, string, negates=False):
self.string = string
self.negates = negates
@@ -114,7 +114,7 @@ def files_and_ids(predicate=None):
return files, ids
-class TestYml(object):
+class TestYml:
"""
Run tests from yaml files.
Multiple input strings having same expected results can be chained.
diff --git a/mkdocs.yml b/mkdocs.yml
index 46698b6..a81600c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,6 +1,6 @@
site_name: GuessIt
-site_url: https://guessit.io
+site_url: https://guessit-io.github.io/guessit
site_description: GuessIt is a python library that extracts as much information as possible from a video filename.
site_author: Rémi Alvergnat <toilal.dev@gmail.com>
diff --git a/pylintrc b/pylintrc
index cd5d0f9..3bf03c8 100644
--- a/pylintrc
+++ b/pylintrc
@@ -1,388 +1,619 @@
-[MASTER]
+[MAIN]
-# Specify a configuration file.
-#rcfile=
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Load and enable all available extensions. Use --list-extensions to see a list
+# all available extensions.
+#enable-all-extensions=
+
+# In error mode, messages with a category besides ERROR or FATAL are
+# suppressed, and no reports are done by default. Error mode is compatible with
+# disabling specific errors.
+#errors-only=
+
+# Always return a 0 (non-error) status code, even if lint errors are found.
+# This is primarily useful in continuous integration scripts.
+#exit-zero=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code.
+extension-pkg-allow-list=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
+# for backward compatibility.)
+extension-pkg-whitelist=
+
+# Return non-zero exit code if any of these messages/categories are detected,
+# even if score is above --fail-under value. Syntax same as enable. Messages
+# specified are enabled, while categories only check already-enabled messages.
+fail-on=
+
+# Specify a score threshold under which the program will exit with error.
+fail-under=10
+
+# Interpret the stdin as a python script, whose filename needs to be passed as
+# the module_or_package argument.
+#from-stdin=
+
+# Files or directories to be skipped. They should be base names, not paths.
+ignore=CVS
+
+# Add files or directories matching the regular expressions patterns to the
+# ignore-list. The regex matches against paths and can be in Posix or Windows
+# format. Because '\' represents the directory delimiter on Windows systems, it
+# can't be used as an escape character.
+ignore-paths=
+
+# Files or directories matching the regular expression patterns are skipped.
+# The regex matches against base names, not paths. The default value ignores
+# Emacs file locks
+ignore-patterns=^\.#
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis). It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
+# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
+# number of processors available to use, and will cap the count on Windows to
+# avoid hangs.
+jobs=1
-# Pickle collected data for later comparisons.
-persistent=yes
+# Control the amount of potential inferred values when inferring a single
+# object. This can help the performance when dealing with large functions or
+# complex, nested conditions.
+limit-inference-results=100
-# List of plugins (as comma separated values of python modules names) to load,
+# List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers.
load-plugins=
-# Use multiple processes to speed up Pylint.
-jobs=1
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Minimum Python version to use for version dependent checks. Will default to
+# the version used to run pylint.
+py-version=3.9
+
+# Discover python modules and packages in the file system subtree.
+recursive=no
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages.
+suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
-# A comma-separated list of package or module names from where C extensions may
-# be loaded. Extensions are loading into the active Python interpreter and may
-# run arbitrary code
-extension-pkg-whitelist=
+# In verbose mode, extra non-checker-related info will be displayed.
+#verbose=
-# Allow optimization of some AST trees. This will activate a peephole AST
-# optimizer, which will apply various small optimizations. For instance, it can
-# be used to obtain the result of joining multiple strings with the addition
-# operator. Joining a lot of strings can lead to a maximum recursion error in
-# Pylint and this flag can prevent that. It has one side effect, the resulting
-# AST will be different than the one from reality.
-optimize-ast=no
+[BASIC]
-[MESSAGES CONTROL]
+# Naming style matching correct argument names.
+argument-naming-style=snake_case
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
+# Regular expression matching correct argument names. Overrides argument-
+# naming-style. If left empty, argument names will be checked with the set
+# naming style.
+#argument-rgx=
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time. See also the "--disable" option for examples.
-#enable=
+# Naming style matching correct attribute names.
+attr-naming-style=snake_case
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-disable=unichr-builtin,backtick,delslice-method,indexing-exception,execfile-builtin,map-builtin-not-iterating,
- intern-builtin,coerce-method,long-builtin,cmp-method,useless-suppression,range-builtin-not-iterating,
- metaclass-assignment,filter-builtin-not-iterating,next-method-called,parameter-unpacking,xrange-builtin,long-suffix,
- setslice-method,zip-builtin-not-iterating,suppressed-message,no-absolute-import,dict-iter-method,raw_input-builtin,
- standarderror-builtin,using-cmp-argument,input-builtin,hex-method,unicode-builtin,reduce-builtin,old-octal-literal,
- dict-view-method,old-ne-operator,coerce-builtin,cmp-builtin,old-raise-syntax,getslice-method,print-statement,
- unpacking-in-except,import-star-module-level,buffer-builtin,round-builtin,file-builtin,reload-builtin,old-division,
- apply-builtin,oct-method,nonzero-method,basestring-builtin,raising-string,too-few-public-methods,too-many-arguments,
- too-many-instance-attributes,bad-builtin,too-many-ancestors,too-few-format-args,fixme,duplicate-code,
- deprecated-lambda,too-many-nested-blocks,useless-object-inheritance,import-outside-toplevel,
- I
+# Regular expression matching correct attribute names. Overrides attr-naming-
+# style. If left empty, attribute names will be checked with the set naming
+# style.
+#attr-rgx=
+# Bad variable names which should always be refused, separated by a comma.
+bad-names=foo,
+ bar,
+ baz,
+ toto,
+ tutu,
+ tata
-[REPORTS]
+# Bad variable names regexes, separated by a comma. If names match any regex,
+# they will always be refused
+bad-names-rgxs=
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=colorized
+# Naming style matching correct class attribute names.
+class-attribute-naming-style=any
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
+# Regular expression matching correct class attribute names. Overrides class-
+# attribute-naming-style. If left empty, class attribute names will be checked
+# with the set naming style.
+#class-attribute-rgx=
-# Tells whether to display a full report or only the messages
-reports=no
+# Naming style matching correct class constant names.
+class-const-naming-style=snake_case
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+# Regular expression matching correct class constant names. Overrides class-
+# const-naming-style. If left empty, class constant names will be checked with
+# the set naming style.
+#class-const-rgx=
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
+# Naming style matching correct class names.
+class-naming-style=PascalCase
+# Regular expression matching correct class names. Overrides class-naming-
+# style. If left empty, class names will be checked with the set naming style.
+#class-rgx=
-[FORMAT]
+# Naming style matching correct constant names.
+const-naming-style=snake_case
-# Maximum number of characters on a single line.
-max-line-length=120
+# Regular expression matching correct constant names. Overrides const-naming-
+# style. If left empty, constant names will be checked with the set naming
+# style.
+#const-rgx=
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
+# Naming style matching correct function names.
+function-naming-style=snake_case
-# List of optional constructs for which whitespace checking is disabled. `dict-
-# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
-# `trailing-comma` allows a space between comma and closing bracket: (a, ).
-# `empty-line` allows space-only lines.
-no-space-check=trailing-comma,dict-separator
+# Regular expression matching correct function names. Overrides function-
+# naming-style. If left empty, function names will be checked with the set
+# naming style.
+#function-rgx=
-# Maximum number of lines in a module
-max-module-lines=1000
+# Good variable names which should always be accepted, separated by a comma.
+good-names=i,
+ j,
+ k,
+ ex,
+ Run,
+ _
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
+# Good variable names regexes, separated by a comma. If names match any regex,
+# they will always be accepted
+good-names-rgxs=
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
+# Include a hint for the correct naming format with invalid-name.
+include-naming-hint=no
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=
+# Naming style matching correct inline iteration names.
+inlinevar-naming-style=any
+# Regular expression matching correct inline iteration names. Overrides
+# inlinevar-naming-style. If left empty, inline iteration names will be checked
+# with the set naming style.
+#inlinevar-rgx=
-[TYPECHECK]
+# Naming style matching correct method names.
+method-naming-style=snake_case
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
+# Regular expression matching correct method names. Overrides method-naming-
+# style. If left empty, method names will be checked with the set naming style.
+#method-rgx=
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis. It
-# supports qualified module names, as well as Unix pattern matching.
-ignored-modules=
+# Naming style matching correct module names.
+module-naming-style=snake_case
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set). This supports can work
-# with qualified names.
-ignored-classes=
+# Regular expression matching correct module names. Overrides module-naming-
+# style. If left empty, module names will be checked with the set naming style.
+#module-rgx=
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E1101 when accessed. Python regular
-# expressions are accepted.
-generated-members=
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
-[BASIC]
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+# These decorators are taken in consideration only for invalid-name.
+property-classes=abc.abstractproperty
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter
+# Regular expression matching correct type variable names. If left empty, type
+# variable names will be checked with the set naming style.
+#typevar-rgx=
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_,cd
+# Naming style matching correct variable names.
+variable-naming-style=snake_case
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
+# Regular expression matching correct variable names. Overrides variable-
+# naming-style. If left empty, variable names will be checked with the set
+# naming style.
+#variable-rgx=
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
+[CLASSES]
-# Regular expression matching correct class attribute names
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+# Warn about protected attribute access inside special methods
+check-protected-access-in-special-methods=no
-# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp,
+ __post_init__
-# Regular expression matching correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,
+ _fields,
+ _replace,
+ _source,
+ _make
-# Naming hint for function names
-function-name-hint=[a-z_][a-z0-9_]{2,30}$
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
-# Regular expression matching correct constant names
-const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=cls
-# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-# Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+[DESIGN]
-# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+# List of regular expressions of class ancestor names to ignore when counting
+# public methods (see R0903)
+exclude-too-few-public-methods=
-# Regular expression matching correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
+# List of qualified class names to ignore when counting class parents (see
+# R0901)
+ignored-parents=
-# Naming hint for variable names
-variable-name-hint=[a-z_][a-z0-9_]{2,30}$
+# Maximum number of arguments for function / method.
+max-args=8
-# Regular expression matching correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
-# Naming hint for method names
-method-name-hint=[a-z_][a-z0-9_]{2,30}$
+# Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
-# Regular expression matching correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
+# Maximum number of branch for function / method body.
+max-branches=12
-# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
+# Maximum number of locals for function / method body.
+max-locals=15
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+# Maximum number of parents for a class (see R0901).
+max-parents=10
-# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
-# Regular expression matching correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
+# Maximum number of return / yield for function / method body.
+max-returns=6
-# Naming hint for argument names
-argument-name-hint=[a-z_][a-z0-9_]{2,30}$
+# Maximum number of statements in function / method body.
+max-statements=50
-# Regular expression matching correct attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=1
-# Naming hint for attribute names
-attr-name-hint=[a-z_][a-z0-9_]{2,30}$
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=^_
+[EXCEPTIONS]
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=builtins.BaseException,
+ builtins.Exception
-[ELIF]
+[FORMAT]
-# Maximum number of nested blocks for function / method body
-max-nested-blocks=5
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-[SPELLING]
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
+# Maximum number of characters on a single line.
+max-line-length=120
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
+# Maximum number of lines in a module.
+max-module-lines=1000
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
-[VARIABLES]
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
+[IMPORTS]
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=_$|dummy
+# List of modules that can be imported at any level, not just the top level
+# one.
+allow-any-import-level=
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,_cb
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=
+
+# Output a graph (.gv or any supported image format) of external dependencies
+# to the given file (report RP0402 must not be disabled).
+ext-import-graph=
+
+# Output a graph (.gv or any supported image format) of all (i.e. internal and
+# external) dependencies to the given file (report RP0402 must not be
+# disabled).
+import-graph=
+
+# Output a graph (.gv or any supported image format) of internal dependencies
+# to the given file (report RP0402 must not be disabled).
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+# Couples of modules and preferred modules, separated by a comma.
+preferred-modules=
[LOGGING]
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+
# Logging modules to check that the string format arguments are in logging
-# function parameter format
+# function parameter format.
logging-modules=logging
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+ CONTROL_FLOW,
+ INFERENCE,
+ INFERENCE_FAILURE,
+ UNDEFINED
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then re-enable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead,
+ duplicate-code
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=c-extension-no-member
+
+
+[METHOD_ARGS]
+
+# List of qualified names (i.e., library.method) which require a timeout
+# parameter e.g. 'requests.api.get,requests.api.post'
+timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+ XXX,
+ TODO
+
+# Regular expression of note tags to take in consideration.
+notes-rgx=
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=8
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit,argparse.parse_error
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'fatal', 'error', 'warning', 'refactor',
+# 'convention', and 'info' which contain the number of messages in each
+# category, as well as 'statement' which is the total number of statements
+# analyzed. This score is used by the global evaluation report (RP0004).
+evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+#output-format=
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
[SIMILARITIES]
+# Comments are removed from the similarity computation
+ignore-comments=yes
+
+# Docstrings are removed from the similarity computation
+ignore-docstrings=yes
+
+# Imports are removed from the similarity computation
+ignore-imports=yes
+
+# Signatures are removed from the similarity computation
+ignore-signatures=yes
+
# Minimum lines number of a similarity.
min-similarity-lines=4
-# Ignore comments when computing similarities.
-ignore-comments=yes
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
+[SPELLING]
-# Ignore imports when computing similarities.
-ignore-imports=no
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+# Spelling dictionary name. Available dictionaries: none. To make it work,
+# install the 'python-enchant' package.
+spelling-dict=
-[MISCELLANEOUS]
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
-[DESIGN]
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
-# Maximum number of arguments for function / method
-max-args=5
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
+[STRING]
-# Maximum number of locals for function / method body
-max-locals=15
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
-# Maximum number of return / yield for function / method body
-max-returns=6
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
-# Maximum number of branch for function / method body
-max-branches=12
-# Maximum number of statements in function / method body
-max-statements=50
+[TYPECHECK]
-# Maximum number of parents for a class (see R0901).
-max-parents=7
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
-# Maximum number of boolean expressions in a if statement
-max-bool-expr=5
+# List of symbolic message names to ignore for Mixin members.
+ignored-checks-for-mixins=no-member,
+ not-async-context-manager,
+ not-context-manager,
+ attribute-defined-outside-init
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
-[IMPORTS]
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=optparse
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
+# Regex pattern to define which classes are considered mixins.
+mixin-class-rgx=.*[Mm]ixin
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
-[CLASSES]
+[VARIABLES]
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
+# List of names allowed to shadow builtins
+allowed-redefined-builtins=
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,_fields,_replace,_source,_make
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
-[EXCEPTIONS]
+# Argument names that match this expression will be ignored.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
diff --git a/setup.py b/setup.py
index 222d738..53a9e6d 100644
--- a/setup.py
+++ b/setup.py
@@ -15,7 +15,7 @@ with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
with io.open(os.path.join(here, 'CHANGELOG.md'), encoding='utf-8') as f:
changelog = f.read()
-install_requires = ['rebulk>=3.1.0', 'babelfish>=0.6.0', 'python-dateutil', 'importlib-resources;python_version<"3.9"']
+install_requires = ['rebulk>=3.2.0', 'babelfish>=0.6.0', 'python-dateutil', 'importlib-resources;python_version<"3.9"']
dev_require = ['tox', 'mkdocs', 'mkdocs-material', 'pyinstaller', 'python-semantic-release']
@@ -43,18 +43,18 @@ args = dict(name='guessit',
'Operating System :: OS Independent',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
- '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',
+ 'Programming Language :: Python :: 3.11',
'Topic :: Multimedia',
'Topic :: Software Development :: Libraries :: Python Modules'
],
keywords='python library release parser name filename movies series episodes animes',
author='Rémi Alvergnat',
author_email='toilal.dev@gmail.com',
- url='https://guessit.io',
+ url='https://guessit-io.github.io/guessit',
download_url='https://pypi.python.org/packages/source/g/guessit/guessit-%s.tar.gz' % version,
license='LGPLv3',
packages=find_packages(),
diff --git a/tox.ini b/tox.ini
index 9998292..85a0575 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py36,py37,py38,py39,py310,pypy3
+envlist = py37,py38,py39,py310,py311,pypy3.8,pypy3.9
[testenv]
commands =
More details
Historical runs
- badpkg: Test unittests3 failed: Test dependencies are unsatisfiable. A common reason is that your testbed is out of date with respect to the archive, and you need to use a current testbed or run apt-get update or use -U.
- success: Merged new upstream version 3.5.0
- push-failed: Failed to push result branch: Connection closed: Connection closed early The remote server unexpectedly closed the connection.
- push-failed: Failed to push result branch: Connection closed: Connection closed early The remote server unexpectedly closed the connection.