upsies.trackers.base.jobs

Abstract base class for tracker jobs

Classes

class upsies.trackers.base.jobs.TrackerJobsBase(*, content_path, tracker, reuse_torrent_path=None, exclude_files=(), btclient_config=None, torrent_destination=None, screenshots_optimization=None, screenshots_tonemapped=False, image_hosts=None, show_poster=False, options=None, common_job_args=None)[source]

Bases: ABC

Base class for tracker-specific jobs

This base class defines general-purpose jobs that can be used by subclasses by returning them in their jobs_before_upload or jobs_after_upload attributes. It also provides all objects that are needed by any one of those jobs.

Job instances are provided as functools.cached_property(), i.e. jobs are created only once per session.

Subclasses that need to run background tasks should pass them to JobBase.add_task() or to TrackerBase.attach_task(). TrackerBase.attach_task() should only be used if there is no appropriate job for the task.

For a description of the arguments see the corresponding properties.

property content_path

Content path to generate metadata for

This is the same object that was passed as initialization argument.

property tracker

TrackerBase subclass

This is the same object that was passed as initialization argument.

property reuse_torrent_path

Path to an existing torrent file that matches content_path

See torrent.create().

property torrent_destination

Where to copy the generated torrent file to or None

This is the same object that was passed as initialization argument.

property exclude_files

Sequence of glob and regular expression patterns to exclude from the generated torrent

See the exclude_files argument of CreateTorrentJob.initialize().

This should also be used by screenshots_job to avoid making screenshots from files that aren’t in the torrent.

property options

Configuration options provided by the user

This is the same object that was passed as initialization argument.

property image_hosts

Sequence of ImagehostBase instances or None

This is the same object that was passed as initialization argument.

property btclient_config

BtclientConfig instance or None

This is the same object that was passed as initialization argument.

property is_bdmv_release

Whether content_path is a Blu-ray release (see is_bluray())

property is_video_ts_release

Whether content_path is a DVD release (see is_dvd())

property is_disc_release

Whether content_path is a Blu-ray or DVD release (see is_disc())

common_job_args(**overload)[source]

Keyword arguments that are passed to all jobs or empty dict

Parameters:

overload – Keyword arguments add or replace values from the initialization argument

abstract property jobs_before_upload

Sequence of jobs that need to finish before upload() can be called

property jobs_after_upload

Sequence of jobs that are started after upload() finished

Note

Jobs returned by this class should have autostart set to False or they will be started before submission is attempted.

By default, this returns add_torrent_job and copy_torrent_job.

property isolated_jobs

Sequence of job names (e.g. "imdb_job") that were singled out by the user (e.g. with a CLI argument) to create only a subset of the usual metadata

If this sequence is empty, all jobs in jobs_before_upload and jobs_after_upload are enabled.

get_job_and_dependencies(*jobs)[source]

Combine all jobs and their dependencies recursively into flat sequence

Parameters:

jobsJobBase instances

Dependencies are gathered from each job’s prejobs.

Warning

This is not a foolproof way to find all dependencies.

Jobs may receive_all() signals from siblings, but only optionally (e.g. AddTorrentJob), so they don’t specify the required siblings as dependencies.

Returns:

Sequence of JobBase instances

property submission_ok

Whether the created metadata should be submitted

The base class implementation returns False if there are any isolated_jobs. Otherwise, it returns True only if all jobs_before_upload have an exit_code of 0 or a falsy is_enabled value.

Subclasses should always call the parent class implementation to ensure all metadata was created successfully.

property imdb

ImdbApi instance

property tmdb

TmdbApi instance

property tvmaze

TvmazeApi instance

get_job_name(name)[source]

Return job name that is unique for this tracker

It’s important for tracker jobs to have unique names to avoid re-using cached output from another tracker’s job with the same name.

Standard jobs have names so that cached output will be re-used by other trackers if possible. This function is mainly for unique and custom jobs that are only used for one tracker but might share the same name with other trackers.

property create_torrent_job

CreateTorrentJob instance

property add_torrent_job

AddTorrentJob instance

property copy_torrent_job

CopyTorrentJob instance

add_torrent_precondition()[source]

Return whether torrent should be postprocessed locally after submission

Postprocessing usually includes adding the torrent to a BitTorrent client or copying it to a directory.

For example, a subclass can overload this method if a submission is only a draft.

property torrent_filepath

Local path to the torrent file created by create_torrent_job

property subtitles

Sequence of Subtitle objects for content_path

property release_name

ReleaseName instance with release_name_translation applied

release_name_separator = None

See ReleaseName.separator

release_name_english_title_before_original = False

See english_title_before_original

release_name_translation = {}

See translate argument of ReleaseName

property release_name_job

TextFieldJob instance with text set to release_name

The text is automatically updated when imdb_job sends an ID.

async update_release_name_from(webdb, webdb_id)[source]

Update release_name_job with web DB information

Parameters:

This is a convenience wrapper around ReleaseName.fetch_info() and TextFieldJob.fetch_text().

property imdb_job

WebDbSearchJob instance

property imdb_id

IMDb ID if imdb_job is finished or None

property tmdb_job

WebDbSearchJob instance

property tmdb_id

TMDb ID if tmdb_job is finished or None

property tvmaze_job

WebDbSearchJob instance

property tvmaze_id

TVmaze ID if tvmaze_job is finished or None

property screenshots_job

ScreenshotsJob instance

The number of screenshots to make is taken the screenshots_count attribute.

property screenshots_precreated

Sequence of user-provided screenshot file paths

The default implementation uses options["screenshots"]. It may be an arbitrarily nested list, which is flattened.

property screenshots_count

How many screenshots to make

The default implementation uses options["screenshots_count"] with None as the default value, which creates a default number of screenshots.

property document_all_videos

Whether to document all videos in the release or just the first/main video

Documenting means creating screenshots and a Mediainfo or BDInfo report.

Extras, and samples should never be documented even if this is enabled. (This is tricky and may fail sometimes.)

For movies and episodes, this has no effect. For seasons, this documents each episode. For Blu-rays and DVDs, document each playlist that is selected by the user.

The default is False.

image_host_config = {}

Dictionary that maps an image hosting service name to config values

common is a special image host whose values are always applied.

Values from a specific image hosting service overload common values.

Example:

>>> image_host_config = {
...     # Generate 300 pixels wide thumbnails for all image hosts.
...     "common": {"thumb_width": 300},
...     # Use specific API key for specific image hosting service just for this tracker.
...     "myhost": {"apikey": "d34db33f"},
... }
property upload_screenshots_job

ImagehostJob instance

poster_max_width = 300

Maximum poster image width

poster_max_height = 600

Maximum poster image height

property poster_job

PosterJob instance

See also get_poster(), get_poster_from_user(), and get_poster_from_webdb().

make_poster_job_precondition()[source]

precondition for poster_job

Subclasses may override this method to selectively provide a poster only if the server doesn’t have one yet.

async get_poster()[source]

Return poster file or URL or None

The default implementation tries to get the poster from the following methods and returns the first truthy return value:

Besides a file or URL, the return value may also be a dictionary with the key poster and the following optional keys:

  • width - Resize width in pixels (keep aspeect ratio)

  • height - Resize height in pixels (keep aspeect ratio)

  • write_to - Write resized poster to this file

  • imagehosts - Sequence of ImagehostBase instances to try to upload the poster to

See PosterJob for more information.

async get_poster_from_user()[source]

Get poster from user (e.g. CLI argument)

The default implementation uses options["poster"].

async get_poster_from_tracker()[source]

Get poster from tracker or any other custom source

The default implementation always returns None.

async get_poster_from_webdb()[source]

Return poster URL from poster_webdb or None

property poster_webdb_job

WebDbSearchJob instance that is used by get_poster_from_webdb() to get a poster image or None if no such instance is enabled and contained in jobs_before_upload

property poster_webdb

WebDbApiBase instance that is used by get_poster_from_webdb() to get a poster image or None if no such instance is enabled and contained in jobs_before_upload

property playlists_job

PlaylistsJob instance

property mediainfo_job

MediainfoJob instance

mediainfo_required_for_bdmv = False

Whether the tracker requires mediainfo output for BDMV Blu-ray releases

property bdinfo_job

BdinfoJob instance

property video_info

Map video file paths to mediainfo/bdinfo reports and screenshot URLs

Every key in the returned dict is a file ID, which is derived from the file path from which mediainfo reports, bdinfo reports and/or screenshot URLs were generated.

Every value in the returned dict is a dict with the keys mediainfos, bdinfos and screenshot_urls. Each value is a sequence, which may be empty.

mediainfos is a sequence of mediainfo reports (str), bdinfos is a sequence of BdinfoReport instances, and screenshot_urls is a sequence of UploadedImage instances.

Note

We allow multiple reports per video file because VIDEO_TS releases may require one report for the .IFO file and another report for the .VOB file.

Season example:

{
  "Foo.S01/Foo.S01E01.mkv": {
    "mediainfos": (
      "<mediainfo report for Foo.S01E01.mkv>",
    ),
    "bdinfos": (),
    "screenshot_urls": (
      <UploadeImage for Foo.S01E01.mkv.0:12:09.png>,
      <UploadeImage for Foo.S01E01.mkv.0:24:12.png>,
    ),
  },
  "Foo.S01/Foo.S01E02.mkv": {
    "mediainfos": (
      "<mediainfo report for Foo.S01E02.mkv>",
    ),
    "bdinfos": (),
    "screenshot_urls": (
      <UploadedImage for Foo.S01E02.mkv.0:13:12.png>,
      <UploadedImage for Foo.S01E02.mkv.0:26:03.png>,
    ),
  },
  ...
}

VIDEO_TS example:

{
  "VIDEO_TS/VTS_03": {
    "mediainfos": (
      "<mediainfo report for VTS_03_0.IFO>",
      "<mediainfo report for VTS_03_2.VOB>",
    ),
    "bdinfos": (),
    "screenshot_urls": (
      <UploadedImage for VTS_03_2.VOB.0:14:58.png>,
      <UploadedImage for VTS_03_2.VOB.0:26:12.png>,
    ),
  },
  "VIDEO_TS/VTS_06": {
    "mediainfos": (
      "<mediainfo report for VTS_06_0.IFO>",
      "<mediainfo report for VTS_06_4.VOB>",
    ),
    "bdinfos": (),
    "screenshot_urls": (
      <UploadedImage for VTS_06_4.VOB.0:12:53.png>,
      <UploadedImage for VTS_06_4.VOB.0:29:32.png>,
    ),
  },
  ...
}

BDMV example:

{
  "BDMV/STREAM/00003.mpls": {
    "mediainfos": (),
    "bdinfos": (
      <BdinfoReport for 00003.mpls>,
    ),
    "screenshot_urls": (
      <UplaodedImage for 00003.mpls.0:11:27.png>,
      <UploadedImage for 00003.mpls.0:21:42.png>,
    ),
  },
  ...
}
property scene_check_job

SceneCheckJob instance

property rules_job

RulesJob instance

property nfo_job

hidden job that reads an *.nfo file

The content of the *.nfo file is available via nfo_text when this job is finished.

This job is mainly required for convenient error handling. You can also call read_nfo() directly and catch ContentError.

property nfo_text

*.nfo file content that was read by nfo_job or None

property confirm_submission_job

Prompt the user right before submission to confirm that all gathered metadata is correct

property login_job

Prompt the user for login credentials if needed and start a user session

property logout_job

Terminate a user session started by login_job

make_precondition(job_attr, precondition=None)[source]

Return precondition function for job

The returned function takes into account jobs_before_upload, jobs_after_upload and isolated_jobs.

Parameters:
  • job_attr (str) –

    Name of the job attribute this precondition is for

    By convention, this should be "<name>_job".

  • precondition (callable) –

    Custom precondition

    precondition must be either None or return anything truthy for the job to get enabled.

get_job_output(job, slice=None, default=<object object>)[source]

Helper method for getting output from job

job must be finished.

Parameters:
  • jobJobBase instance

  • sliceint to get a specific item from job’s output, None to return all output as a list, or a slice object to return only one or more items of the output

  • default – Default value if job is not finished or getting slice from job’s output fails.

Raises:

RuntimeError – if job is not finished or getting slice from output raises an IndexError

Returns:

list or str

get_job_attribute(job, attribute, default=<object object>)[source]

Helper method for getting an attribute from job

Parameters:
  • jobJobBase instance

  • attribute (str) – Name of attribute to get from job

  • default – Default value if job is not finished

Raises:
get_relative_file_path(file_path)[source]

Return file_path relative to content_path

The first path component of the returned path is the last component of content_path.

Raises:

ValueError – if file_path is not a subpath of content_path

read_nfo(*, strip=False)[source]

Read *.nfo file

If no file path is supplied by the user, find *.nfo file beneath content_path.

If no *.nfo file is found, return None.

Parameters:

path – Path to NFO file or directory that contains an NFO file or None to use content_path

See string.read_nfo() for more information.

Returns:

if *.nfo file content or None if no *.nfo file is found

Raises:

errors.ContentError – if an *.nfo file is found but cannot be read

generate_promotion_bbcode(format='[align=right][size=1]{message}[/size][/align]')[source]

Return self promotional BBcode

If only_description in options is set, return an empty string.

Parameters:

format (str) –

Template for the returned string

The placeholder {message} is replaced with the promotional message.