TorrentFile API Documentation
CLI
Module
torrentfile.
cli
Command Line Interface for TorrentFile project.
This module provides the primary command line argument parser for the torrentfile package. The main_script function is automatically invoked when called from command line, and parses accompanying arguments.
Functions: main_script: process command line arguments and run program.
TorrentFileHelpFormatter
— Formatting class for help tips provided by the CLI.
create_command
(
args
)
(`Result`) — Execute the create CLI sub-command to create a new torrent metafile.create_magnet
(
metafile
)
(`str`) — Create a magnet URI from a Bittorrent meta file.edit_command
(
args
)
(`str`) — Execute the edit CLI sub-command with provided arguments.main
(
)
— Initiate main function for CLI script.main_script
(
args
)
— Initialize Command Line Interface for torrentfile.recheck_command
(
args
)
(`str` :) — Execute recheck CLI sub-command.
torrentfile.cli
Command Line Interface for TorrentFile project.
This module provides the primary command line argument parser for the torrentfile package. The main_script function is automatically invoked when called from command line, and parses accompanying arguments.
Functions: main_script: process command line arguments and run program.
TorrentFileHelpFormatter (HelpFormatter)
Formatting class for help tips provided by the CLI.
Subclasses Argparse.HelpFormatter.
Source code in torrentfile\cli.py
class TorrentFileHelpFormatter(HelpFormatter):
"""
Formatting class for help tips provided by the CLI.
Subclasses Argparse.HelpFormatter.
"""
def __init__(self, prog, width=75, max_help_positions=60):
"""Construct HelpFormat class for usage output.
Parameters
----------
prog : `str`
Name of the program.
width : `int`
Max width of help message output.
max_help_positions : `int`
max length until line wrap.
"""
super().__init__(
prog, width=width, max_help_position=max_help_positions
)
def _split_lines(self, text, _):
"""Split multiline help messages and remove indentation.
Parameters
----------
text : `str`
text that needs to be split
_ : `int`
max width for line.
"""
lines = text.split("\n")
return [line.strip() for line in lines if line]
def _format_text(self, text):
"""Format text for cli usage messages.
Parameters
----------
text : `str`
Pre-formatted text.
Returns
-------
`str` :
Formatted text from input.
"""
text = text % dict(prog=self._prog) if "%(prog)" in text else text
text = self._whitespace_matcher.sub(" ", text).strip()
return text + "\n\n"
def _join_parts(self, part_strings):
"""Combine different sections of the help message.
Parameters
----------
part_strings : `list`
List of argument help messages and headers.
Returns
-------
`str` :
Fully formatted help message for CLI.
"""
parts = self.format_headers(part_strings)
return super()._join_parts(parts)
@staticmethod
def format_headers(parts):
"""Format help message section headers.
Parameters
----------
parts : `list`
List of individual lines for help message.
Returns
-------
`list` :
Input list with formatted section headers.
"""
if parts and parts[0].startswith("usage:"):
parts[0] = "Usage\n=====\n " + parts[0][6:]
headings = [i for i in range(len(parts)) if parts[i].endswith(":\n")]
for i in headings[::-1]:
parts[i] = parts[i][:-2].title()
underline = "".join(["\n", "-" * len(parts[i]), "\n"])
parts.insert(i + 1, underline)
return parts
__init__(self, prog, width=75, max_help_positions=60)
special
Construct HelpFormat class for usage output.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
prog |
`str` |
Name of the program. |
required |
width |
`int` |
Max width of help message output. |
75 |
max_help_positions |
`int` |
max length until line wrap. |
60 |
Source code in torrentfile\cli.py
def __init__(self, prog, width=75, max_help_positions=60):
"""Construct HelpFormat class for usage output.
Parameters
----------
prog : `str`
Name of the program.
width : `int`
Max width of help message output.
max_help_positions : `int`
max length until line wrap.
"""
super().__init__(
prog, width=width, max_help_position=max_help_positions
)
format_headers(parts)
staticmethod
Format help message section headers.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
parts |
`list` |
List of individual lines for help message. |
required |
Source code in torrentfile\cli.py
@staticmethod
def format_headers(parts):
"""Format help message section headers.
Parameters
----------
parts : `list`
List of individual lines for help message.
Returns
-------
`list` :
Input list with formatted section headers.
"""
if parts and parts[0].startswith("usage:"):
parts[0] = "Usage\n=====\n " + parts[0][6:]
headings = [i for i in range(len(parts)) if parts[i].endswith(":\n")]
for i in headings[::-1]:
parts[i] = parts[i][:-2].title()
underline = "".join(["\n", "-" * len(parts[i]), "\n"])
parts.insert(i + 1, underline)
return parts
create_command(args)
Execute the create CLI sub-command to create a new torrent metafile.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
args |
`Namespace` |
positional and optional CLI arguments. |
required |
Returns:
Type | Description |
---|---|
`Result` |
object containing the path to created metafile and its contents. |
Source code in torrentfile\cli.py
def create_command(args):
"""Execute the create CLI sub-command to create a new torrent metafile.
Parameters
----------
args : `Namespace`
positional and optional CLI arguments.
Returns
-------
`Result`
object containing the path to created metafile and its contents.
"""
kwargs = {
"noprogress": args.noprogress,
"url_list": args.url_list,
"path": args.content,
"announce": args.announce + args.tracker,
"piece_length": args.piece_length,
"source": args.source,
"private": args.private,
"outfile": args.outfile,
"comment": args.comment,
}
logger.debug("Program has entered torrent creation mode.")
if args.meta_version == "2":
torrent = TorrentFileV2(**kwargs)
elif args.meta_version == "3":
torrent = TorrentFileHybrid(**kwargs)
else:
torrent = TorrentFile(**kwargs)
logger.debug("Completed torrent files meta info assembly.")
outfile, meta = torrent.write()
if args.magnet:
create_magnet(outfile)
args.torrent = torrent
args.kwargs = kwargs
args.outfile = outfile
args.meta = meta
logger.debug("New torrent file (%s) has been created.", str(outfile))
return args
create_magnet(metafile)
Create a magnet URI from a Bittorrent meta file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
metafile |
(`Namespace`||`str`) |
Namespace class for CLI arguments. |
required |
Returns:
Type | Description |
---|---|
`str` |
created magnet URI. |
Source code in torrentfile\cli.py
def create_magnet(metafile):
"""Create a magnet URI from a Bittorrent meta file.
Parameters
----------
metafile : (`Namespace`||`str`)
Namespace class for CLI arguments.
Returns
-------
`str`
created magnet URI.
"""
import os
from hashlib import sha1 # nosec
from urllib.parse import quote_plus
import pyben
if hasattr(metafile, "metafile"):
metafile = metafile.metafile
if not os.path.exists(metafile):
raise FileNotFoundError
meta = pyben.load(metafile)
info = meta["info"]
binfo = pyben.dumps(info)
infohash = sha1(binfo).hexdigest().upper() # nosec
logger.info("Magnet Info Hash: %s", infohash)
scheme = "magnet:"
hasharg = "?xt=urn:btih:" + infohash
namearg = "&dn=" + quote_plus(info["name"])
if "announce-list" in meta:
announce_args = [
"&tr=" + quote_plus(url)
for urllist in meta["announce-list"]
for url in urllist
]
else:
announce_args = ["&tr=" + quote_plus(meta["announce"])]
full_uri = "".join([scheme, hasharg, namearg] + announce_args)
logger.info("Created Magnet URI %s", full_uri)
sys.stdout.write(full_uri)
return full_uri
edit_command(args)
Execute the edit CLI sub-command with provided arguments.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
args |
`Namespace` |
positional and optional CLI arguments. |
required |
Returns:
Type | Description |
---|---|
`str` |
path to edited torrent file. |
Source code in torrentfile\cli.py
def edit_command(args):
"""Execute the edit CLI sub-command with provided arguments.
Parameters
----------
args : `Namespace`
positional and optional CLI arguments.
Returns
-------
`str`
path to edited torrent file.
"""
metafile = args.metafile
logger.info("Editing %s Meta File", str(args.metafile))
editargs = {
"url-list": args.url_list,
"announce": args.announce,
"source": args.source,
"private": args.private,
"comment": args.comment,
}
return edit_torrent(metafile, editargs)
main()
Initiate main function for CLI script.
Source code in torrentfile\cli.py
def main():
"""Initiate main function for CLI script."""
main_script()
main_script(args=None)
Initialize Command Line Interface for torrentfile.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
args |
`list` |
Commandline arguments. default=None |
None |
Source code in torrentfile\cli.py
def main_script(args=None):
"""Initialize Command Line Interface for torrentfile.
Parameters
----------
args : `list`
Commandline arguments. default=None
"""
if not args:
if sys.argv[1:]:
args = sys.argv[1:]
else:
args = ["-h"]
parser = ArgumentParser(
"torrentfile",
description="""
CLI Tool for creating, checking, editing... Bittorrent meta files.
TorrentFile supports all versions of torrent files.
""",
prefix_chars="-",
formatter_class=TorrentFileHelpFormatter,
conflict_handler="resolve",
)
parser.add_argument(
"-i",
"--interactive",
action="store_true",
dest="interactive",
help="select program options interactively",
)
parser.add_argument(
"-V",
"--version",
action="version",
version=f"torrentfile v{torrentfile.__version__}",
help="show program version and exit",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
dest="debug",
help="output debug information",
)
subparsers = parser.add_subparsers(
title="Actions",
dest="command",
metavar="<create> <edit> <magnet> <recheck>",
)
create_parser = subparsers.add_parser(
"c",
help="""
Create a torrent meta file.
""",
prefix_chars="-",
aliases=["create", "new"],
formatter_class=TorrentFileHelpFormatter,
)
create_parser.add_argument(
"-a",
"--announce",
action="store",
dest="announce",
metavar="<url>",
nargs="+",
default=[],
help="Alias for -t/--tracker",
)
create_parser.add_argument(
"-p",
"--private",
action="store_true",
dest="private",
help="Create a private torrent file",
)
create_parser.add_argument(
"-s",
"--source",
action="store",
dest="source",
metavar="<source>",
help="Useful for cross-seeding",
)
create_parser.add_argument(
"-m",
"--magnet",
action="store_true",
dest="magnet",
help="Output Magnet Link after creation completes",
)
create_parser.add_argument(
"-c",
"--comment",
action="store",
dest="comment",
metavar="<comment>",
help="Include a comment in file metadata",
)
create_parser.add_argument(
"-o",
"--out",
action="store",
dest="outfile",
metavar="<path>",
help="Output path for created .torrent file",
)
create_parser.add_argument(
"-t",
"--tracker",
action="store",
dest="tracker",
metavar="<url>",
nargs="+",
default=[],
help="""One or more Bittorrent tracker announce url(s).""",
)
create_parser.add_argument(
"--noprogress",
action="store_true",
dest="noprogress",
help="""
Disable showing the progress bar during torrent creation.
(Minimially improves performance of torrent file creation.)
""",
)
create_parser.add_argument(
"--meta-version",
default="1",
choices=["1", "2", "3"],
action="store",
dest="meta_version",
metavar="<int>",
help="""
Bittorrent metafile version.
Options = 1, 2 or 3.
(1) = Bittorrent v1 (Default)
(2) = Bittorrent v2
(3) = Bittorrent v1 & v2 hybrid
""",
)
create_parser.add_argument(
"--piece-length",
action="store",
dest="piece_length",
metavar="<int>",
help="""
Fixed amount of bytes for each chunk of data. (Default: None)
Acceptable input values include integers 14-24, which
will be interpreted as the exponent for 2^n, or any perfect
power of two integer between 16Kib and 16MiB (inclusive).
Examples:: [--piece-length 14] [--piece-length 16777216]
""",
)
create_parser.add_argument(
"-w",
"--web-seed",
action="store",
dest="url_list",
metavar="<url>",
nargs="+",
help="""
One or more url(s) linking to a http server hosting
the torrent contents. This is useful if the torrent
tracker is ever unreachable. Example:: -w url1 url2 url3
""",
)
create_parser.add_argument(
"content",
action="store",
metavar="<content>",
help="Path to content file or directory",
)
create_parser.set_defaults(func=create_command)
edit_parser = subparsers.add_parser(
"e",
help="""
Edit existing torrent meta file.
""",
aliases=["edit"],
prefix_chars="-",
formatter_class=TorrentFileHelpFormatter,
)
edit_parser.add_argument(
"metafile",
action="store",
help="path to *.torrent file",
metavar="<*.torrent>",
)
edit_parser.add_argument(
"--tracker",
action="store",
dest="announce",
metavar="<url>",
nargs="+",
help="""
Replace current list of tracker/announce urls with one or more space
seperated Bittorrent tracker announce url(s).
""",
)
edit_parser.add_argument(
"--web-seed",
action="store",
dest="url_list",
metavar="<url>",
nargs="+",
help="""
Replace current list of web-seed urls with one or more space seperated url(s)
""",
)
edit_parser.add_argument(
"--private",
action="store_true",
help="Make torrent private.",
dest="private",
)
edit_parser.add_argument(
"--comment",
help="Replaces any existing comment with <comment>",
metavar="<comment>",
dest="comment",
action="store",
)
edit_parser.add_argument(
"--source",
action="store",
dest="source",
metavar="<source>",
help="Replaces current source with <source>",
)
edit_parser.set_defaults(func=edit_command)
magnet_parser = subparsers.add_parser(
"m",
help="""
Create magnet url from an existing Bittorrent meta file.
""",
aliases=["magnet"],
prefix_chars="-",
formatter_class=TorrentFileHelpFormatter,
)
magnet_parser.add_argument(
"metafile",
action="store",
help="Path to Bittorrent meta file.",
metavar="<*.torrent>",
)
magnet_parser.set_defaults(func=create_magnet)
check_parser = subparsers.add_parser(
"r",
help="""
Calculate amount of torrent meta file's content is found on disk.
""",
aliases=["recheck", "check"],
prefix_chars="-",
formatter_class=TorrentFileHelpFormatter,
)
check_parser.add_argument(
"metafile",
action="store",
metavar="<*.torrent>",
help="path to .torrent file.",
)
check_parser.add_argument(
"content",
action="store",
metavar="<content>",
help="path to content file or directory",
)
check_parser.set_defaults(func=recheck_command)
args = parser.parse_args(args)
if args.debug:
torrentfile.set_level(logging.DEBUG)
logger.debug(str(args))
if args.interactive:
return select_action()
return args.func(args)
recheck_command(args)
Execute recheck CLI sub-command.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
args |
`Namespace` |
positional and optional arguments. |
required |
Source code in torrentfile\cli.py
def recheck_command(args):
"""Execute recheck CLI sub-command.
Parameters
----------
args : `Namespace`
positional and optional arguments.
Returns
-------
`str` :
The percentage of content currently saved to disk.
"""
logger.debug("Program entering Recheck mode.")
metafile = args.metafile
content = args.content
logger.debug("Checking %s against %s contents", metafile, content)
checker = Checker(metafile, content)
logger.debug("Completed initialization of the Checker class")
result = checker.results()
logger.info("Final result for %s recheck: %s", metafile, result)
sys.stdout.write(str(result))
sys.stdout.flush()
return result