[9] more overlay updates

This commit is contained in:
meisnate12 2022-04-20 00:06:42 -04:00
parent ff0ee3dce2
commit 33709b28ee
11 changed files with 155 additions and 299 deletions

View file

@ -1 +1 @@
1.16.5-develop8
1.16.5-develop9

View file

@ -141,6 +141,22 @@ libraries:
- file: config/Overlays.yml
```
### Remove Overlays
You can remove overlays from a library by adding `remove_overlays: true` to overlay_path
```yaml
libraries:
TV Shows:
metadata_path:
- file: config/TV Shows.yml
overlay_path:
- file: config/Overlays.yml
- remove_overlays: ture
```
* This will remove all overlays when run and not generate new ones.
### Missing Path
The `missing_path` attribute is used to define where to save the "missing items" YAML file. This file is used to store information about media which is missing from the Plex library compared to what is expected from the Metadata file.

View file

@ -30,7 +30,6 @@ The available attributes for the operations attribute are as follows
| `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode<br>**Values:** `default`: Library default<br>`hide`: Hide Collection<br>`hide_items`: Hide Items in this Collection<br>`show_items`: Show this Collection and its Items<table class="clearTable"><tr><td>`default`</td><td>Library default</td></tr><tr><td>`hide`</td><td>Hide Collection</td></tr><tr><td>`hide_items`</td><td>Hide Items in this Collection</td></tr><tr><td>`show_items`</td><td>Show this Collection and its Items</td></tr></table> |
| `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title<br>**Values:** `true` or `false` |
| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.<br>**Values:** `true` or `false` |
| `remove_overlays` | Search through every title and removes all overlays.<br>**Values:** `true` or `false` |
| `split_duplicates` | Splits all duplicate movies/shows found in this library<br>**Values:** `true` or `false` |
| `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given<br>**Values:** List or comma separated string of tags |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

View file

@ -1,175 +0,0 @@
# Image Overlay Detail
In order to add an overlay to a set of items you must add `item_overlay: OVERLAY_NAME` to the collection config, where `OVERLAY_NAME` matches the exact name of a folder in your `overlays` directory.
Your `overlays` directory must be inside your config folder structured like below:
```
config
├── overlays
│ ├── OVERLAY_NAME
│ ├── overlay.png
```
* `OVERLAY_NAME` is the folder contacting your `overlay.png` and its name is what you give `item_overlay` to refer to this specific overlay.
* `overlay.png` is the overlay file with the banner. You can create you're own with this [PSD](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/overlays.psd). The font can be found [here](https://www.dafontfree.net/freefonts-eurostile-extended-f123859.htm).
* An item can only be in one overlay search so make sure you exclude other searches when using multiple overlays.
* Posters will be backed up in the overlay director and if an item is removed from the search the original poster should be added back.
* `revert_overlay` can be added to an overlay collection configuration to revert all movies changed by that overlay back to their original posters.
## Examples
### Example Folder Structure
This is an example of the default set found [here](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/config/overlays) which would have 5 overlay options `4K`, `4K-Dolby`, `4K-HDR`, `Dolby`, and `HDR` and have a directory structured like below:
```
config
├── config.yml
├── Movies.yml
├── TV Shows.yml
├── overlays
│ ├── 4K
│ ├── overlay.png
│ ├── 4K-Dolby
│ ├── overlay.png
│ ├── 4K-HDR
│ ├── overlay.png
│ ├── Dolby
│ ├── overlay.png
│ ├── HDR
│ ├── overlay.png
```
### Alternative URL Images
The alternative way to specify your overlay image is do use the `name` and either `url` or `git` attributes like so.
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay:
name: 4K
url: https://raw.githubusercontent.com/wiki/meisnate12/Plex-Meta-Manager/overlay.png
build_collection: false
```
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay:
name: 4K
git: yozora/Overlays/4K/overlay
build_collection: false
```
### Examples Collection Configs
#### 4K Overlay Only
![4K Overlay](overlay-4k.png)
Add a 4K overlay to all 4K Movies
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay: 4K
build_collection: false
```
#### 4K and HDR Overlays
Here's an example of how you could add `4K`, `4K-HDR`, and `HDR` overlays
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
hdr: false
item_overlay: 4K
build_collection: false
4K-HDR Overlay:
plex_search:
all:
resolution: 4K
hdr: true
item_overlay: 4K-HDR
build_collection: false
HDR Overlay:
plex_search:
all:
hdr: true
filters:
resolution.not: 4K
item_overlay: HDR
build_collection: false
```
#### 4K, HDR, Dolby Overlays
Here's an example of how you could add `4K`, `4K-HDR`, `4K-Dolby`, `Dolby`, and `HDR` overlays
**Note: This only works is your filenames have a tag in them for Dolby files as Plex cannot detect dolby yet**
```yaml
collections:
4K:
plex_search:
all:
resolution: 4K
hdr: false
filters:
filepath.not: DoVi
item_overlay: 4K
build_collection: false
4K-HDR:
plex_search:
all:
resolution: 4K
hdr: true
filters:
filepath.not: DoVi
item_overlay: 4K-HDR
build_collection: false
4K-Dolby:
plex_search:
all:
resolution: 4K
filters:
filepath: DoVi
item_overlay: 4K-Dolby
build_collection: false
HDR:
plex_search:
all:
hdr: true
filters:
filepath.not: DoVi
resolution.not: 4K
item_overlay: HDR
build_collection: false
Dolby:
plex_all: true
filters:
filepath: DoVi
resolution.not: 4K
item_overlay: Dolby
build_collection: false
```
## User Generated Overlays
![Language Overlay](overlay-language.png)

View file

@ -4,7 +4,7 @@ Overlay files are used to create and maintain overlays within the Plex libraries
Overlays and templates are defined within one or more Overlay files, which are linked to libraries in the [Libraries Attribute](../config/libraries.md#overlay-path) within the [Configuration File](../config/configuration.md).
**To remove all overlays use the `remove_overlays` library operation.**
**To remove all overlays add `remove_overlays: true` to the `overlay_path` [Libraries Attribute](../config/libraries.md#remove-overlays).**
**To change a single overlay original image either replace the image in the assets folder or remove the `Overlay` shared label and then PMM will overlay the new image**
@ -73,9 +73,11 @@ overlays:
imdb_chart: top_movies
```
### Remove Overlay
### Supress Overlays
You can add `remove_overlay` to an overlay definition and give it a list or comma separated string of overlay names you want removed from this item if this overlay is attached to the item.
You can add `supress_overlays` to an overlay definition and give it a list or comma separated string of overlay names you want suppressed from this item if this overlay is attached to the item.
So in this example if the `4K-HDR` overlay matches an item then the `4K` and `HDR` overlays will also match. The `supress_overlays` attribute on `4K-HDR` will stop the overlays specified (`4K` and `HDR`) from also being applied.
```yaml
overlays:
@ -88,7 +90,7 @@ overlays:
all:
hdr: true
4K-HDR:
remove_overlay:
supress_overlays:
- 4K
- HDR
plex_search:
@ -129,7 +131,9 @@ These filter media items added to the collection by any of the Builders.
* [Filters](filters)
## Examples
## Example
### Example Overlay File
```yaml
overlays:
@ -153,4 +157,18 @@ overlays:
plex_all: true
filters:
has_dolby_vision: true
```
```
### Example Folder Structure
```
config
├── config.yml
├── Movies.yml
├── TV Shows.yml
├── Overlays.yml
├── overlays
│ ├── 4K.png
│ ├── Dolby.png
│ ├── HDR.png
```

View file

@ -97,7 +97,7 @@ boolean_details = [
scheduled_boolean = ["visible_library", "visible_home", "visible_shared"]
string_details = ["sort_title", "content_rating", "name_mapping"]
ignored_details = [
"smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "remove_overlay",
"smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "supress_overlays",
"delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "collection_level", "overlay",
"validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection"
]
@ -190,7 +190,7 @@ custom_sort_builders = [
"mal_popular", "mal_favorite", "mal_suggested", "mal_userlist", "mal_season", "mal_genre", "mal_studio"
]
episode_parts_only = ["plex_pilots"]
overlay_only = ["overlay", "remove_overlay"]
overlay_only = ["overlay", "supress_overlays"]
overlay_attributes = [
"filters", "limit", "show_missing", "save_missing", "missing_only_released", "minimum_items", "cache_builders", "tmdb_region"
] + all_builders + overlay_only
@ -264,7 +264,7 @@ class CollectionBuilder:
self.data[attr] = new_attributes[attr]
methods[attr.lower()] = attr
self.remove_overlays = []
self.supress_overlays = []
if self.overlay:
if "overlay" in methods:
logger.debug("")
@ -308,14 +308,14 @@ class CollectionBuilder:
if not os.path.exists(overlay_path):
raise Failed(f"{self.Type} Error: Overlay Image not found at: {overlay_path}")
if "remove_overlay" in methods:
if "supress_overlays" in methods:
logger.debug("")
logger.debug("Validating Method: remove_overlay")
logger.debug(f"Value: {data[methods['remove_overlay']]}")
if data[methods["remove_overlay"]]:
self.remove_overlays = util.get_list(data[methods["remove_overlay"]])
logger.debug("Validating Method: supress_overlays")
logger.debug(f"Value: {data[methods['supress_overlays']]}")
if data[methods["supress_overlays"]]:
self.supress_overlays = util.get_list(data[methods["supress_overlays"]])
else:
logger.error(f"{self.Type} Error: remove_overlay attribute is blank")
logger.error(f"{self.Type} Error: supress_overlays attribute is blank")
if self.playlist:
if "libraries" in methods:

View file

@ -577,7 +577,6 @@ class ConfigFile:
"mass_originally_available_update": None,
"mass_imdb_parental_labels": None,
"remove_title_parentheses": None,
"remove_overlays": None
}
display_name = f"{params['name']} ({params['mapping_name']})" if lib and "library_name" in lib and lib["library_name"] else params["mapping_name"]
@ -671,8 +670,6 @@ class ConfigFile:
params["update_blank_track_titles"] = check_for_attribute(lib["operations"], "update_blank_track_titles", var_type="bool", default=False, save=False)
if "remove_title_parentheses" in lib["operations"]:
params["remove_title_parentheses"] = check_for_attribute(lib["operations"], "remove_title_parentheses", var_type="bool", default=False, save=False)
if "remove_overlays" in lib["operations"]:
params["remove_overlays"] = check_for_attribute(lib["operations"], "remove_overlays", var_type="bool", default=False, save=False)
if "mass_collection_mode" in lib["operations"]:
try:
params["mass_collection_mode"] = util.check_collection_mode(lib["operations"]["mass_collection_mode"])
@ -753,12 +750,16 @@ class ConfigFile:
params["skip_library"] = True
params["overlay_path"] = []
params["remove_overlays"] = False
if lib and "overlay_path" in lib:
if not lib["overlay_path"]:
raise Failed("Config Error: overlay_path attribute is blank")
files = util.load_files(lib["overlay_path"], "overlay_path")
if not files:
raise Failed("Config Error: No Paths Found for overlay_path")
for file in util.get_list(lib["overlay_path"], split=False):
if isinstance(file, dict) and "remove_overlays" in file and file["remove_overlays"] is True:
params["remove_overlays"] = True
params["overlay_path"] = files
logger.info("")

View file

@ -3,7 +3,7 @@ from modules import util
from modules.builder import CollectionBuilder
from modules.util import Failed
from plexapi.exceptions import BadRequest
from plexapi.video import Show, Season, Episode
from plexapi.video import Movie, Show, Season, Episode
from PIL import Image
logger = util.logger
@ -18,12 +18,12 @@ class Overlays:
logger.info("")
logger.separator(f"{self.library.name} Library Overlays")
logger.info("")
overlay_rating_keys = {}
item_keys = {}
overlay_to_keys = {}
key_to_item = {}
os.makedirs(self.library.overlay_backup, exist_ok=True)
overlay_updated = {}
overlay_images = {}
item_overlays = {}
key_to_overlays = {}
if self.library.remove_overlays:
logger.info("")
logger.separator(f"Removing Overlays for the {self.library.name} Library")
@ -37,8 +37,8 @@ class Overlays:
logger.separator(f"Gathering Items for {k} Overlay", space=False, border=False)
if builder.overlay not in overlay_rating_keys:
overlay_rating_keys[builder.overlay] = []
if builder.overlay not in overlay_to_keys:
overlay_to_keys[builder.overlay] = []
if builder.filters or builder.tmdb_filters:
logger.info("")
@ -54,19 +54,19 @@ class Overlays:
builder.filter_and_save_items(builder.gather_ids(method, value))
if builder.added_items:
for item in builder.added_items:
item_keys[item.ratingKey] = item
if item.ratingKey not in overlay_rating_keys[builder.overlay]:
overlay_rating_keys[builder.overlay].append(item.ratingKey)
key_to_item[item.ratingKey] = item
if item.ratingKey not in overlay_to_keys[builder.overlay]:
overlay_to_keys[builder.overlay].append(item.ratingKey)
if builder.remove_overlays:
for rk in overlay_rating_keys[builder.overlay]:
for remove_overlay in builder.remove_overlays:
if remove_overlay in overlay_rating_keys and rk in overlay_rating_keys[remove_overlay]:
overlay_rating_keys[remove_overlay].remove(rk)
if builder.supress_overlays:
for rk in overlay_to_keys[builder.overlay]:
for supress_overlay in builder.supress_overlays:
if supress_overlay in overlay_to_keys and rk in overlay_to_keys[supress_overlay]:
overlay_to_keys[supress_overlay].remove(rk)
except Failed as e:
logger.error(e)
for overlay_name, over_keys in overlay_rating_keys.items():
for overlay_name, over_keys in overlay_to_keys.items():
clean_name, _ = util.validate_filename(overlay_name)
image_compare = None
if self.config.Cache:
@ -76,17 +76,17 @@ class Overlays:
overlay_updated[overlay_name] = not image_compare or str(overlay_size) != str(image_compare)
overlay_images[overlay_name] = Image.open(overlay_file).convert("RGBA")
for over_key in over_keys:
if over_key not in item_overlays:
item_overlays[over_key] = []
item_overlays[over_key].append(overlay_name)
if over_key not in key_to_overlays:
key_to_overlays[over_key] = (key_to_item[over_key], [])
key_to_overlays[over_key][1].append(overlay_name)
if self.config.Cache:
self.config.Cache.update_image_map(overlay_name, f"{self.library.image_table_name}_overlays", overlay_name, overlay_size)
def find_poster_url(plex_item):
if self.library.is_movie:
if isinstance(plex_item, Movie):
if plex_item.ratingKey in self.library.movie_rating_key_map:
return self.config.TMDb.get_movie(self.library.movie_rating_key_map[plex_item.ratingKey]).poster_url
elif self.library.is_show:
elif isinstance(plex_item, (Show, Season, Episode)):
check_key = plex_item.ratingKey if isinstance(plex_item, Show) else plex_item.show().ratingKey
tmdb_id = self.config.Convert.tvdb_to_tmdb(self.library.show_rating_key_map[check_key])
if isinstance(plex_item, Show) and plex_item.ratingKey in self.library.show_rating_key_map:
@ -97,7 +97,7 @@ class Overlays:
return self.config.TMDb.get_episode(tmdb_id, plex_item.seasonNumber, plex_item.episodeNumber).still_url
def get_overlay_items(libtype=None):
return [o for o in self.library.search(label="Overlay", libtype=libtype) if o.ratingKey not in item_overlays]
return [o for o in self.library.search(label="Overlay", libtype=libtype) if o.ratingKey not in key_to_overlays]
remove_overlays = get_overlay_items()
if self.library.is_show:
@ -129,102 +129,99 @@ class Overlays:
poster_location = find_poster_url(item)
if poster_location:
self.library.upload_poster(item, poster_location, url=is_url)
self.library.edit_tags("label", item, remove_tags=["Overlay"])
self.library.edit_tags("label", item, remove_tags=["Overlay"], do_print=False)
if original:
os.remove(original)
else:
logger.error(f"No Poster found to restore for {item.title}")
logger.exorcise()
if item_overlays:
if key_to_overlays:
logger.info("")
logger.separator(f"Applying Overlays for the {self.library.name} Library")
logger.info("")
for i, (over_key, (item, over_names)) in enumerate(sorted(key_to_overlays.items(), key=lambda io: io[1][0].title), 1):
try:
logger.ghost(f"Overlaying: {i}/{len(key_to_overlays)} {item.title}")
image_compare = None
overlay_compare = None
if self.config.Cache:
image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays")
overlay_compare = [] if overlay_compare is None else util.get_list(overlay_compare)
has_overlay = any([item_tag.tag.lower() == "overlay" for item_tag in item.labels])
for i, (over_key, over_names) in enumerate(item_overlays.items(), 1):
try:
item = item_keys[over_key]
logger.ghost(f"Overlaying: {i}/{len(item_overlays)} {item.title}")
image_compare = None
overlay_compare = None
if self.config.Cache:
image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays")
overlay_compare = [] if overlay_compare is None else util.get_list(overlay_compare)
has_overlay = any([item_tag.tag.lower() == "overlay" for item_tag in item.labels])
overlay_change = False if has_overlay else True
if not overlay_change:
for oc in overlay_compare:
if oc not in over_names:
overlay_change = True
if not overlay_change:
for over_name in over_names:
if over_name not in overlay_compare or overlay_updated[over_name]:
overlay_change = True
overlay_change = False if has_overlay else True
if not overlay_change:
for oc in overlay_compare:
if oc not in over_names:
overlay_change = True
if not overlay_change:
for over_name in over_names:
if over_name not in overlay_compare or overlay_updated[over_name]:
overlay_change = True
clean_name, _ = util.validate_filename(item.title)
poster, _, item_dir = self.library.find_assets(
name="poster" if self.library.asset_folders else clean_name,
folder_name=clean_name if self.library.asset_folders else None,
prefix=f"{item.title}'s "
)
clean_name, _ = util.validate_filename(item.title)
poster, _, item_dir = self.library.find_assets(
name="poster" if self.library.asset_folders else clean_name,
folder_name=clean_name if self.library.asset_folders else None,
prefix=f"{item.title}'s "
)
has_original = False
changed_image = False
new_backup = None
if poster:
if image_compare and str(poster.compare) != str(image_compare):
changed_image = True
elif has_overlay:
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")
has_original = None
changed_image = False
new_backup = None
if poster:
if image_compare and str(poster.compare) != str(image_compare):
changed_image = True
elif has_overlay:
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")
else:
self.library.reload(item)
new_backup = find_poster_url(item)
if new_backup is None:
new_backup = item.posterUrl
else:
self.library.reload(item)
new_backup = find_poster_url(item)
if new_backup is None:
new_backup = item.posterUrl
else:
self.library.reload(item)
new_backup = item.posterUrl
if new_backup:
changed_image = True
image_response = self.config.get(new_backup)
if image_response.status_code >= 400:
raise Failed(f"Overlay Error: Poster Download Failed for {item.title}")
i_ext = "jpg" if image_response.headers["Content-Type"] == "image/jpeg" else "png"
backup_image_path = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.{i_ext}")
with open(backup_image_path, "wb") as handler:
handler.write(image_response.content)
while util.is_locked(backup_image_path):
time.sleep(1)
has_original = backup_image_path
new_backup = item.posterUrl
if new_backup:
changed_image = True
image_response = self.config.get(new_backup)
if image_response.status_code >= 400:
raise Failed(f"Overlay Error: Poster Download Failed for {item.title}")
i_ext = "jpg" if image_response.headers["Content-Type"] == "image/jpeg" else "png"
backup_image_path = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.{i_ext}")
with open(backup_image_path, "wb") as handler:
handler.write(image_response.content)
while util.is_locked(backup_image_path):
time.sleep(1)
has_original = backup_image_path
poster_uploaded = False
if changed_image or overlay_change:
new_poster = Image.open(poster.location if poster else has_original).convert("RGBA")
temp = os.path.join(self.library.overlay_folder, f"temp.png")
try:
for over_name in over_names:
new_poster = new_poster.resize(overlay_images[over_name].size, Image.ANTIALIAS)
new_poster.paste(overlay_images[over_name], (0, 0), overlay_images[over_name])
new_poster.save(temp, "PNG")
self.library.upload_poster(item, temp)
self.library.edit_tags("label", item, add_tags=["Overlay"])
self.library.reload(item)
poster_uploaded = True
logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}")
except (OSError, BadRequest) as e:
logger.stacktrace()
raise Failed(f"Overlay Error: {e}")
poster_compare = None
if poster is None and has_original is None:
logger.error(f"Overlay Error: No poster found for {item.title}")
elif changed_image or overlay_change:
new_poster = Image.open(poster.location if poster else has_original).convert("RGBA")
temp = os.path.join(self.library.overlay_folder, f"temp.png")
try:
for over_name in over_names:
new_poster = new_poster.resize(overlay_images[over_name].size, Image.ANTIALIAS)
new_poster.paste(overlay_images[over_name], (0, 0), overlay_images[over_name])
new_poster.save(temp, "PNG")
self.library.upload_poster(item, temp)
self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False)
self.library.reload(item)
poster_compare = poster.compare if poster else item.thumb
logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}")
except (OSError, BadRequest) as e:
logger.stacktrace()
raise Failed(f"Overlay Error: {e}")
if self.config.Cache:
if poster_uploaded:
self.config.Cache.update_image_map(
item.ratingKey, self.library.image_table_name, item.thumb,
poster.compare if poster else item.thumb, overlay=','.join(over_names)
)
except Failed as e:
logger.error(e)
if self.config.Cache and poster_compare:
self.config.Cache.update_image_map(item.ratingKey, self.library.image_table_name, item.thumb,
poster_compare, overlay=','.join(over_names))
except Failed as e:
logger.error(e)
logger.exorcise()

View file

@ -293,7 +293,7 @@ def update_libraries(config):
if not config.library_first and not config.test_mode and not collection_only:
if not overlays_only and library.library_operation:
library.Operations.run_operations()
if not operations_only and library.overlay_files or library.remove_overlays:
if not operations_only and (library.overlay_files or library.remove_overlays):
library.Overlays.run_overlays()
logger.remove_library_handler(library.mapping_name)