diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml
index bd7f02b86..76154fe4d 100644
--- a/.github/workflows/formatting_check.yml
+++ b/.github/workflows/formatting_check.yml
@@ -6,7 +6,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Install dependencies
- - uses: actions/checkout@v3
- - uses: paolorechia/pox@v1.0.1
+ uses: actions/checkout@v3
+
+ - name: Run formatting check
+ uses: paolorechia/pox@v1.0.1
with:
tox_env: "format_check"
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index d91966011..f5edb70f9 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -42,12 +42,12 @@ Non-Programming
compiling a library of freely-licensed music files (preferably with
incorrect metadata) for testing and measurement.
- Think you have a nice config or cool use-case for beets? We’d love to
- hear about it! Submit a post to our `our
- forums `__ under the “Show and Tell”
- category for a chance to get featured in `the
+ hear about it! Submit a post to our `discussion board
+ `__
+ under the “Show and Tell” category for a chance to get featured in `the
docs `__.
-- Consider helping out in `our forums `__
- by responding to support requests or driving some new discussions.
+- Consider helping out fellow users by by `responding to support requests
+ `__ .
Programming
-----------
@@ -119,7 +119,8 @@ If this is your first time contributing to an open source project,
welcome! If you are confused at all about how to contribute or what to
contribute, take a look at `this great
tutorial `__, or stop by our
-`forums `__ if you have any questions.
+`discussion board `__
+if you have any questions.
We maintain a list of issues we reserved for those new to open source
labeled `“first timers
diff --git a/README.rst b/README.rst
index 42f770278..0813bd6cc 100644
--- a/README.rst
+++ b/README.rst
@@ -115,12 +115,11 @@ Contact
you'd like to see prioritized over others.
* Need help/support, would like to start a discussion, have an idea for a new
feature, or would just like to introduce yourself to the team? Check out
- `GitHub Discussions`_ or `Discourse`_!
+ `GitHub Discussions`_!
.. _GitHub Discussions: https://github.com/beetbox/beets/discussions
.. _issue tracker: https://github.com/beetbox/beets/issues
.. _open a new ticket: https://github.com/beetbox/beets/issues/new/choose
-.. _Discourse: https://discourse.beets.io/
Authors
-------
diff --git a/README_kr.rst b/README_kr.rst
index a6a95ec5a..c12fc8b71 100644
--- a/README_kr.rst
+++ b/README_kr.rst
@@ -104,5 +104,5 @@ Read More
`Adrian Sampson`_ 와 많은 사람들의 지지를 받아 Beets를 만들었다.
돕고 싶다면 `forum`_.를 방문하면 된다.
-.. _forum: https://discourse.beets.io
+.. _forum: https://github.com/beetbox/beets/discussions/
.. _Adrian Sampson: https://www.cs.cornell.edu/~asampson/
diff --git a/beets/dbcore/query.py b/beets/dbcore/query.py
index 03f85ac77..9806d5226 100644
--- a/beets/dbcore/query.py
+++ b/beets/dbcore/query.py
@@ -166,8 +166,8 @@ class FieldQuery(Query, Generic[P]):
def __repr__(self) -> str:
return (
- "{0.__class__.__name__}({0.field!r}, {0.pattern!r}, "
- "{0.fast})".format(self)
+ f"{self.__class__.__name__}({self.field!r}, {self.pattern!r}, "
+ f"fast={self.fast})"
)
def __eq__(self, other) -> bool:
@@ -205,7 +205,7 @@ class NoneQuery(FieldQuery[None]):
return obj.get(self.field) is None
def __repr__(self) -> str:
- return "{0.__class__.__name__}({0.field!r}, {0.fast})".format(self)
+ return f"{self.__class__.__name__}({self.field!r}, {self.fast})"
class StringFieldQuery(FieldQuery[P]):
@@ -471,7 +471,7 @@ class CollectionQuery(Query):
return clause, subvals
def __repr__(self) -> str:
- return "{0.__class__.__name__}({0.subqueries!r})".format(self)
+ return f"{self.__class__.__name__}({self.subqueries!r})"
def __eq__(self, other) -> bool:
return super().__eq__(other) and self.subqueries == other.subqueries
@@ -511,8 +511,8 @@ class AnyFieldQuery(CollectionQuery):
def __repr__(self) -> str:
return (
- "{0.__class__.__name__}({0.pattern!r}, {0.fields!r}, "
- "{0.query_class.__name__})".format(self)
+ f"{self.__class__.__name__}({self.pattern!r}, {self.fields!r}, "
+ f"{self.query_class.__name__})"
)
def __eq__(self, other) -> bool:
@@ -577,7 +577,7 @@ class NotQuery(Query):
return not self.subquery.match(obj)
def __repr__(self) -> str:
- return "{0.__class__.__name__}({0.subquery!r})".format(self)
+ return f"{self.__class__.__name__}({self.subquery!r})"
def __eq__(self, other) -> bool:
return super().__eq__(other) and self.subquery == other.subquery
@@ -883,6 +883,9 @@ class Sort:
def __eq__(self, other) -> bool:
return type(self) is type(other)
+ def __repr__(self):
+ return f"{self.__class__.__name__}()"
+
class MultipleSort(Sort):
"""Sort that encapsulates multiple sub-sorts."""
@@ -934,7 +937,7 @@ class MultipleSort(Sort):
return items
def __repr__(self):
- return f"MultipleSort({self.sorts!r})"
+ return f"{self.__class__.__name__}({self.sorts!r})"
def __hash__(self):
return hash(tuple(self.sorts))
@@ -972,10 +975,9 @@ class FieldSort(Sort):
return sorted(objs, key=key, reverse=not self.ascending)
def __repr__(self) -> str:
- return "<{}: {}{}>".format(
- type(self).__name__,
- self.field,
- "+" if self.ascending else "-",
+ return (
+ f"{self.__class__.__name__}"
+ f"({self.field!r}, ascending={self.ascending!r})"
)
def __hash__(self) -> int:
diff --git a/beets/importer.py b/beets/importer.py
index f7c6232aa..55ee29226 100644
--- a/beets/importer.py
+++ b/beets/importer.py
@@ -412,7 +412,7 @@ class ImportSession:
def ask_resume(self, toppath):
"""If import of `toppath` was aborted in an earlier session, ask
- user if she wants to resume the import.
+ user if they want to resume the import.
Determines the return value of `is_resuming(toppath)`.
"""
diff --git a/beets/library.py b/beets/library.py
index d0019fb80..7507f5d34 100644
--- a/beets/library.py
+++ b/beets/library.py
@@ -151,6 +151,12 @@ class PathQuery(dbcore.FieldQuery):
dir_blob,
)
+ def __repr__(self) -> str:
+ return (
+ f"{self.__class__.__name__}({self.field!r}, {self.pattern!r}, "
+ f"fast={self.fast}, case_sensitive={self.case_sensitive})"
+ )
+
# Library-specific field types.
@@ -1518,9 +1524,12 @@ def parse_query_parts(parts, model_cls):
case_insensitive = beets.config["sort_case_insensitive"].get(bool)
- return dbcore.parse_sorted_query(
+ query, sort = dbcore.parse_sorted_query(
model_cls, parts, prefixes, case_insensitive
)
+ log.debug("Parsed query: {!r}", query)
+ log.debug("Parsed sort: {!r}", sort)
+ return query, sort
def parse_query_string(s, model_cls):
diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py
index 5bdd27705..3385e4221 100644
--- a/beetsplug/discogs.py
+++ b/beetsplug/discogs.py
@@ -425,6 +425,8 @@ class DiscogsPlugin(BeetsPlugin):
catalogno = result.data["labels"][0].get("catno")
labelid = result.data["labels"][0].get("id")
+ cover_art_url = self.select_cover_art(result)
+
# Additional cleanups (various artists name, catalog number, media).
if va:
artist = config["va_name"].as_str()
@@ -474,8 +476,19 @@ class DiscogsPlugin(BeetsPlugin):
discogs_albumid=discogs_albumid,
discogs_labelid=labelid,
discogs_artistid=artist_id,
+ cover_art_url=cover_art_url,
)
+ def select_cover_art(self, result):
+ """Returns the best candidate image, if any, from a Discogs `Release` object."""
+ if result.data.get("images") and len(result.data.get("images")) > 0:
+ # The first image in this list appears to be the one displayed first
+ # on the release page - even if it is not flagged as `type: "primary"` - and
+ # so it is the best candidate for the cover art.
+ return result.data.get("images")[0].get("uri")
+
+ return None
+
def format(self, classification):
if classification:
return (
diff --git a/beetsplug/edit.py b/beetsplug/edit.py
index 1e934317d..323dd9e41 100644
--- a/beetsplug/edit.py
+++ b/beetsplug/edit.py
@@ -220,7 +220,7 @@ class EditPlugin(plugins.BeetsPlugin):
- `fields`: The set of field names to edit (or None to edit
everything).
"""
- # Present the YAML to the user and let her change it.
+ # Present the YAML to the user and let them change it.
success = self.edit_objects(objs, fields)
# Save the new data.
@@ -370,7 +370,7 @@ class EditPlugin(plugins.BeetsPlugin):
if not obj._db or obj.id is None:
obj.id = -i
- # Present the YAML to the user and let her change it.
+ # Present the YAML to the user and let them change it.
fields = self._get_fields(album=False, extra=[])
success = self.edit_objects(task.items, fields)
diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py
index f1b012a5f..93d3f2c57 100644
--- a/beetsplug/fetchart.py
+++ b/beetsplug/fetchart.py
@@ -1098,7 +1098,7 @@ class CoverArtUrl(RemoteArtSource):
image_url = None
try:
# look for cover_art_url on album or first track
- if album.cover_art_url:
+ if album.get("cover_art_url"):
image_url = album.cover_art_url
else:
image_url = album.items().get().cover_art_url
diff --git a/docs/_static/beets.css b/docs/_static/beets.css
new file mode 100644
index 000000000..243ae74cc
--- /dev/null
+++ b/docs/_static/beets.css
@@ -0,0 +1,12 @@
+html[data-theme="light"] {
+ --pst-color-secondary: #a23632;
+}
+html[data-theme="light"] {
+ --pst-color-inline-code: #a23632;
+}
+
+/* beetroot red: #a23632 */
+/* beetroot green: #1B5801 */
+/* beetroot green light: rgb(27, 150, 50) */
+/* pydata teal (primary): #126A7E */
+/* pydata violet (secondary): #7D0E70 */
diff --git a/docs/_static/beets_logo.png b/docs/_static/beets_logo.png
new file mode 100644
index 000000000..0359260ad
Binary files /dev/null and b/docs/_static/beets_logo.png differ
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 13e75a904..a6ae89a7a 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -17,6 +17,8 @@ Major new features:
New features:
+* :doc:`plugins/discogs`: supply a value for the `cover_art_url` attribute, for use by `fetchart`.
+ :bug:`429`
* :ref:`update-cmd`: added ```-e``` flag for excluding fields from being updated.
* :doc:`/plugins/deezer`: Import rank and other attributes from Deezer during import and add a function to update the rank of existing items.
:bug:`4841`
diff --git a/docs/conf.py b/docs/conf.py
index 4514bbe2b..0220ab48b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -59,5 +59,16 @@ man_pages = [
),
]
-# Options for Alabaster theme
-html_theme_options = {"fixed_sidebar": True}
+# Options for pydata theme
+html_theme = 'pydata_sphinx_theme'
+html_theme_options = {
+ 'collapse_navigation': True,
+ "logo": {
+ "text": "beets",
+ },
+ "pygment_light_style": "bw",
+}
+html_title = "beets"
+html_logo = "_static/beets_logo.png"
+html_static_path = ['_static']
+html_css_files = ['beets.css']
diff --git a/docs/faq.rst b/docs/faq.rst
index 814f87b7a..44c8fa25c 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -6,7 +6,7 @@ Got a question that isn't answered here? Try the `discussion board`_, or
:ref:`filing an issue ` in the bug tracker.
.. _mailing list: https://groups.google.com/group/beets-users
-.. _discussion board: https://discourse.beets.io
+.. _discussion board: https://github.com/beetbox/beets/discussions/
.. contents::
:local:
diff --git a/docs/guides/tagger.rst b/docs/guides/tagger.rst
index d47ee3c4a..68ad908e8 100644
--- a/docs/guides/tagger.rst
+++ b/docs/guides/tagger.rst
@@ -309,4 +309,4 @@ If we haven't made the process clear, please post on `the discussion
board`_ and we'll try to improve this guide.
.. _the mailing list: https://groups.google.com/group/beets-users
-.. _the discussion board: https://discourse.beets.io
+.. _the discussion board: https://github.com/beetbox/beets/discussions/
diff --git a/docs/index.rst b/docs/index.rst
index 961c0f42d..2ad2fca06 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -20,7 +20,7 @@ where you think this documentation can be improved.
.. _beets: https://beets.io/
.. _the mailing list: https://groups.google.com/group/beets-users
.. _file a bug: https://github.com/beetbox/beets/issues
-.. _the discussion board: https://discourse.beets.io
+.. _the discussion board: https://github.com/beetbox/beets/discussions/
Contents
--------
diff --git a/setup.py b/setup.py
index c96f1fe24..e55a48e17 100755
--- a/setup.py
+++ b/setup.py
@@ -132,7 +132,7 @@ setup(
],
"docs": [
"sphinx",
- "sphinx_rtd_theme",
+ "pydata_sphinx_theme",
],
# Plugin (optional) dependencies:
"absubmit": ["requests"],
diff --git a/test/plugins/test_edit.py b/test/plugins/test_edit.py
index 04af56117..413db7cf6 100644
--- a/test/plugins/test_edit.py
+++ b/test/plugins/test_edit.py
@@ -72,8 +72,8 @@ class ModifyFileMocker:
class EditMixin:
"""Helper containing some common functionality used for the Edit tests."""
- def assertItemFieldsModified(
- self, library_items, items, fields=[], allowed=["path"] # noqa
+ def assertItemFieldsModified( # noqa
+ self, library_items, items, fields=[], allowed=["path"]
):
"""Assert that items in the library (`lib_items`) have different values
on the specified `fields` (and *only* on those fields), compared to
@@ -135,11 +135,11 @@ class EditCommandTest(unittest.TestCase, TestHelper, EditMixin):
self.teardown_beets()
self.unload_plugins()
- def assertCounts(
+ def assertCounts( # noqa
self,
mock_write,
album_count=ALBUM_COUNT,
- track_count=TRACK_COUNT, # noqa
+ track_count=TRACK_COUNT,
write_call_count=TRACK_COUNT,
title_starts_with="",
):
diff --git a/test/test_autotag.py b/test/test_autotag.py
index c0268910d..130b69419 100644
--- a/test/test_autotag.py
+++ b/test/test_autotag.py
@@ -1078,9 +1078,9 @@ class EnumTest(_common.TestCase):
"""
def test_ordered_enum(self):
- OrderedEnumClass = match.OrderedEnum(
+ OrderedEnumClass = match.OrderedEnum( # noqa
"OrderedEnumTest", ["a", "b", "c"]
- ) # noqa
+ )
self.assertLess(OrderedEnumClass.a, OrderedEnumClass.b)
self.assertLess(OrderedEnumClass.a, OrderedEnumClass.c)
self.assertLess(OrderedEnumClass.b, OrderedEnumClass.c)
diff --git a/test/test_datequery.py b/test/test_datequery.py
index 50066af66..73175f9ec 100644
--- a/test/test_datequery.py
+++ b/test/test_datequery.py
@@ -132,9 +132,9 @@ class DateIntervalTest(unittest.TestCase):
self.assertContains("..", date=datetime.min)
self.assertContains("..", "1000-01-01T00:00:00")
- def assertContains(
+ def assertContains( # noqa
self, interval_pattern, date_pattern=None, date=None
- ): # noqa
+ ):
if date is None:
date = _date(date_pattern)
(start, end) = _parse_periods(interval_pattern)
diff --git a/tox.ini b/tox.ini
index 4fa8d897c..fb0027177 100644
--- a/tox.ini
+++ b/tox.ini
@@ -33,7 +33,9 @@ commands =
[testenv:docs]
basepython = python3.10
-deps = sphinx<4.4.0
+deps =
+ sphinx<4.4.0
+ pydata_sphinx_theme
commands = sphinx-build -W -q -b html docs {envtmpdir}/html {posargs}
# checks all links in the docs