Giter Club home page Giter Club logo

stig's Introduction

stig

https://img.shields.io/pypi/v/stig.svg https://img.shields.io/pypi/status/stig.svg https://img.shields.io/pypi/l/stig.svg https://img.shields.io/pypi/pyversions/stig.svg https://img.shields.io/github/last-commit/rndusr/stig.svg

https://raw.githubusercontent.com/rndusr/stig/master/screenshot.png

stig is a TUI (text user interface) and CLI (command line interface) client for the BitTorrent client Transmission.

stig is in maintenance mode. The code needs to be split it into multiple projects and the current client doesn’t really support more clients besides Transmission. Please don’t make any feature PRs. The more time I invest in reviewing and testing code that is going to be dead, the less time I have for future-proofing stig.

Features

  • Filters are used to select torrents for listing, starting/stopping, deleting, etc
  • Tabs allow you to open and switch between multiple lists (torrents, peers, files, etc)
  • Commands do almost everything, and they can be invoked
    • through single- or multi-key (think emacs) keybindings,
    • by entering them in a command prompt in the TUI (think vi) with tab completion,
    • by providing them as CLI arguments when invoking stig (think git),
    • or by listing them in an rc file which is automatically loaded.
  • Color themes support 16 and 256 colors
  • Complete built-in documentation with help command or --help argument
  • Full API abstraction layer makes it possible to add support for other BitTorrent clients with RPC interfaces (contributors are welcome)

Examples

Add two torrents, one by file and one by hash, and exit

$ stig add /path/to/some.torrent d4d6b73851fe3288e40389a8e1fb98124a9b9ba5

Connect to non-default host and present the TUI

$ stig set connect.host torrents.local

Print all uploading and/or downloading torrents on localhost:9092 and exit

$ stig set connect.port 9092 \; ls active

List torrents with more than 50 seeds, then remove them

$ stig ls 'seeds>50'
$ stig rm 'seeds>50'

Stop down/uploading torrents with /foo/ in their download path and a ratio above 10

$ stig stop 'path~/foo/&ratio>10'

Open two tabs with different torrent lists:

  • slowly uploading torrents with /foo/ in their download path
  • small or well-seeded torrents, sorted by size (ascending) and number of seeds (descending)
$ stig tab ls 'path~/foo/&rate-up<10k' \; tab ls 'size<500M|seeds>=1k' --sort 'size,!seeds'

Configuration and Scripting

All configuration is done in an rc file, which is just a script containing a list of commands (think vim and .vimrc) that are executed during startup. The default rc file is $XDG_CONFIG_HOME/stig/rc. XDG_CONFIG_HOME defaults to $HOME/.config if not set. Because a default rc file is empty, it is not created automatically to avoid clutter.

See stig help cfgman for more information.

Example rc file

# Host that runs Transmission daemon
set connect.host example.org
set connect.port 123

# Update torrent/peer/file/etc lists every 10 seconds
set tui.poll 10

# Default columns in torrent lists
set columns.torrents name ratio rate-up rate-down

# Open a few tabs on startup
tab ls active --sort !%downloaded,path,!rate
tab ls paused --sort !%downloaded --columns name,%downloaded,ratio,size
tab ls isolated --sort tracker --columns name,path

Run different rc files either with stig -c path/to/file or with the rc command. You can even turn them into executables with the shebang #!/path/to/stig -Tc (-T disables the TUI, -c specifies the rc file).

Example maintenance script

#!/path/to/stig -Tc
rm path=/path/to/torrents/trash
pause seeds>100
start seeds<20&size>10G|seeds<50&size>20G

Installation

The latest release is always on PyPI.

Packages

Pipx (recommended)

Pipx installs applications in self-contained virtual environments in $HOME/.local/pipx/ that include all dependencies. Executables are sym-linked to $HOME/.local/bin/.

$ pipx install stig
$ pipx upgrade stig
$ pipx uninstall stig

Pip

pip installs applications with their dependencies in the system-wide (/usr/local) or user-wide ($HOME/.local) environment.

$ pip3 install stig         # Installs in /usr/local/
$ pip3 install --user stig  # Installs in $HOME/.local/

To update, add the --upgrade or -U option.

Extras

The following extras are available to enable optional features:

setproctitle
Strip arguments from process title when running in tmux session (this requires Python headers; e.g. apt-get install libpython3-dev)
proxy
Tunnel the connection to the Transmission daemon through a SOCKS5, SOCKS4 or HTTP proxy

To install stig with dependencies for an extra:

$ pipx install 'stig[setproctitle,proxy]'              # For pipx version>=0.15.0.0
$ pipx install stig --spec 'stig[setproctitle,proxy]'  # For pipx version<0.15.0.0

Development version

To install the latest development version of stig with pipx:

$ pipx install 'git+https://github.com/rndusr/stig.git#egg=stig'              # For pipx version>=0.15.0.0
$ pipx install stig --spec 'git+https://github.com/rndusr/stig.git#egg=stig'  # For pipx version<0.15.0.0

Developing

To make your code changes effective immediately, you can either run python3 -m stig <ARGUMENTS> in the project directory or use pip3’s --editable option.

Run tests with your system’s Python version

To run the tests with the Python version that is installed on your system, simply run make test in the project directory. This creates a virtual environment in ./venv, installs stig and its dependencies in there and runs all tests.

If you want to only run tests for a specific module or package:

  1. Create a virtual environment with all dependencies: make venv
  2. Activate the virtual environment: source venv/bin/activate
  3. Pass any path in the tests directory to pytest: pytest tests/settings_test

Run tests with all supported Python versions

  1. Install and set up pyenv.
  2. With pyenv, install the supported Python versions listed in .setup.py.
  3. In stig’s project directory, create a virtual environment with all dependencies: make venv
  4. Activate the virtual environment: source venv/bin/activate
  5. Run the tests for each supported Python version: tox
  6. Pass arguments to pytest: tox -- --exitfirst tests/settings_test

Requirements

Contributing

Pull requests, bug reports, features requests, ideas for improvement and all other constructive contributions are welcome.

If you want to contribute code and get stuck, don’t know where to even begin, or just to make sure you’re not duplicating someone else’s efforts, open an issue.

Please submit your custom themes if you would like them to be included in stig.

License

stig is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

stig's People

Contributors

anjandev avatar apexo avatar bachoseven avatar biobox avatar blajda avatar hellothisisflo avatar kazuoteramoto avatar kianmeng avatar lenormf avatar luzpaz avatar marcelpaulo avatar rndusr avatar rr- avatar rsekman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stig's Issues

Installation fails on OpenBSD 6.0 with Python 3.5.2

Trying to install stage on OpenBSD 6.0 with Python 3.5.2 but i get an error during installation (regular install and git clone dev-install both give me the same error). Haven't spent a lot time trying to resolve it myself yet, will do it later if nobody gave me any hints/clues by then :-)

uname -a

OpenBSD torrentbox.local 6.0 GENERIC#2148 amd64

python

Python 3.5.2 (default, Jul 26 2016, 01:52:58)
[GCC 4.2.1 20070719 ] on openbsd6

pip3 install stig

Collecting stig
Downloading stig-0.1.0a0.tar.gz (103kB)
100% |################################| 112kB 201kB/s
Collecting urwid>=1.3.0 (from stig)
Using cached urwid-1.3.1.tar.gz
Collecting aiohttp>=0.22.5 (from stig)
Using cached aiohttp-1.2.0.tar.gz
Collecting urwidtrees>=1.0.1.1 (from stig)
Using cached urwidtrees-1.0.1.1.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-build-7q9we0i6/urwidtrees/setup.py", line 4, in
import urwidtrees.version as v
File "/tmp/pip-build-7q9we0i6/urwidtrees/urwidtrees/init.py", line 6, in
from .decoration import DecoratedTree, CollapsibleTree
File "/tmp/pip-build-7q9we0i6/urwidtrees/urwidtrees/decoration.py", line 4, in
import urwid
ImportError: No module named 'urwid'

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-7q9we0i6/urwidtrees/

Failure to run 'stig info id=<id>': KeyError: 'name'

I have just installed stig from source, was playing around to learn how to use it and stumbled across a problem: I wanted to show info about a torrent using its torrent id as filter, so I tried:

stig info id=43

and this is the result:

paulo@monk:~/src/stig$ stig summary id=43
Traceback (most recent call last):
  File "/home/paulo/.local/bin/stig", line 11, in <module>
    load_entry_point('stig==0.8.3a0', 'console_scripts', 'stig')()
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/__init__.py", line 24, in run
    main.run()
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/main.py", line 169, in run
    if not run_commands():
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/main.py", line 151, in run_commands
    success = cmdmgr.run_sync(clicmds, on_error=log.error)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/__init__.py", line 576, in run_sync
    self._maybe_run_callbacks(process, on_success, on_error)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/__init__.py", line 529, in _maybe_run_callbacks
    raise exc
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/__init__.py", line 243, in _catch_exceptions
    success = callabee(*args, **kwargs)
  File "/usr/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
    return future.result()
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/__init__.py", line 243, in _catch_exceptions
    success = callabee(*args, **kwargs)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/base/torrent.py", line 106, in run
    return await self.display_summary(tfilter)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/cli/torrent.py", line 55, in display_summary
    torrent = await self.get_torrent(tfilter, keys=('id',))
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/commands/base/_mixin.py", line 40, in get_torrent
    torrents = TorrentSorter(('name',)).apply(response.torrents)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/client/sorters/__init__.py", line 106, in apply
    items = sorter(items, inplace=inplace, item_getter=item_getter)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/client/sorters/__init__.py", line 35, in __call__
    items = sorted(items, key=key_getter, reverse=reverse)
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/client/sorters/__init__.py", line 30, in key_getter
    return keyfunc(item_getter(item))
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/client/sorters/torrent.py", line 26, in <lambda>
    'name':              _SortSpec(lambda t: t['name'].lower(),
  File "/home/paulo/.local/lib/python3.6/site-packages/stig-0.8.3a0-py3.6.egg/stig/client/aiotransmission/torrent.py", line 496, in __getitem__
    value = raw[fields[0]]
KeyError: 'name'
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7fb41a4e5940>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7fb41e03a668>, 159348.330755063)]']
connector: <aiohttp.connector.TCPConnector object at 0x7fb41a4e5748>

I'm running Xubuntu 17.10 and this is how I installed stig

git clone https://github.com/rndusr/stig
cd stig
python3 setup.py install --user

The torrent id I was trying to filter against exists, here's the output from transmission-remote:

ID     Done       Have  ETA           Up    Down  Ratio  Status       Name
  43   100%    7.53 GB  Done         0.0     0.0    0.5  Idle         Sneaky Pete
  47   100%   271.5 MB  Unknown      0.0     0.0    6.3  Idle         Good.Girls.S01E03.HDTV.x264-SVA[eztv].mkv
Sum:           7.81 GB               0.0     0.0

Special characters

I've not succeeded at setting password with special characters.
Test pass was generated with pwgen -sy 30

Error:

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 56, in __init__
    urldict[attr] = getattr(parsed_url, attr)
  File "/usr/lib/python3.6/urllib/parse.py", line 159, in port
    port = int(port, 10)
ValueError: invalid literal for int() with base 10: 'some,:('

...

stig.client.errors.URLParserError: Invalid URL: https://user:'some,:(/long)@=pass`->here'@example.com:443

Though it opens TUI if there is no / in the password

set tab title

Enhancement suggestion: The ability to control the title text of each tab created.

This would be for the sake of giving a short, easily readable name to long and complex filters, or reducing the horizontal space taken up for multiple tabs.

Crash on incomplete metadata

'%uploaded' : lambda raw: raw['uploadedEver'] / raw['totalSize'] * 100,

stig 0.7.3a crashes after a few seconds when I have a magnet transfer whose metadata is not yet loaded. Since totalSize is 0 it will cause a division by zero error.

Backtrace:

Traceback (most recent call last):
  File "/home/user/.local/bin/stig", line 11, in <module>
    sys.exit(run())
  File "/home/user/.local/lib/python3.5/site-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/home/user/.local/lib/python3.5/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/main.py", line 212, in run
    urwidloop.run()
  File "/home/user/.local/lib/python3.5/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/home/user/.local/lib/python3.5/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/urwidpatches.py", line 56, in run
    raise self._exc_info
  File "/usr/lib/python3.5/asyncio/events.py", line 125, in _run
    self._callback(*self._args)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/main_loop.py", line 1289, in faux_idle_callback
    callback()
  File "/home/user/.local/lib/python3.5/site-packages/urwid/main_loop.py", line 564, in entering_idle
    self.draw_screen()
  File "/home/user/.local/lib/python3.5/site-packages/urwid/main_loop.py", line 578, in draw_screen
    canvas = self._topmost_widget.render(self.screen_size, focus=True)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/widget.py", line 1750, in render
    canv = get_delegate(self).render(size, focus=focus)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/container.py", line 1526, in render
    canv = w.render((maxcol, rows), focus=focus and item_focus)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/tabs.py", line 129, in render
    canvas = current_widget.render(size_content, focus)
  File "/home/user/.local/lib/python3.5/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/torrent/tlist.py", line 116, in render
    self._update_listitems()
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/torrent/tlist.py", line 131, in _update_listitems
    tw.update(tdict[tid])
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/torrent/tlist.py", line 41, in update
    widget.update(torrent)
  File "/home/user/.local/lib/python3.5/site-packages/stig/tui/torrent/__init__.py", line 88, in update
    self.data.update(data)
  File "/home/user/.local/lib/python3.5/site-packages/stig/client/aiotransmission/torrent.py", line 388, in __getitem__
    value = _MODIFY[key](raw)
  File "/home/user/.local/lib/python3.5/site-packages/stig/client/aiotransmission/torrent.py", line 324, in <lambda>
    '%uploaded'         : lambda raw: raw['uploadedEver'] / raw['totalSize'] * 100,
ZeroDivisionError: division by zero

No interface to trackers list

stig seems to expose only the first tracker for each torrent as a column in the torrent list. No other trackers are displayed, and are touched only by announce. There is no interface to the trackerAdd, trackerRemove, and trackerReplace mutators.

Crash when reading an invalid URL with non integer port number

Since the last update, I'm experiencing a crash every time I try to reach <all> tab. Here is the traceback.

I'm confident it's not a problem with my torrents because with the previous version it doesn't happen. In addition, I couldn't find the specific torrent responsible for the bug. I ran this shell commands to make sure there is no such torrent with a tracker with such a port number:

for t in `transmission-remote -ne --list | awk '$1 ~ /[0-9]+/ {print $1}'`;do
    if transmission-remote -ne --torrent "$t" --info-trackers |\
        awk '$1 == "Tracker" && $2 ~ /[0-9]:/ && $3 ~ /udp:\/\/tracker\.coppersurfer\.tk:69692710\/announce/ { exit 0}'; then
        transmission-remote -ne --torrent "$t" --info
    fi
done

Cannot load theme from home

I'm copying the default.theme to my home and and trying to set it like this

set tui.theme /home/quite/.config/stig/my.theme

But end up getting this when starting:

Exception in callback _CommandBase.__init__.<locals>.<lambda>(<Task finishe...te 'theme'",)>) at /usr/lib/python3.6/site-packages/stig/commands/__init__.py:222
handle: <Handle _CommandBase.__init__.<locals>.<lambda>(<Task finishe...te 'theme'",)>) at /usr/lib/python3.6/site-packages/stig/commands/__init__.py:222>
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/stig/tui/hooks.py", line 57, in _set_theme
    tui.theme.load(cfg['tui.theme'].value, tui.urwidscreen)
AttributeError: module 'stig.tui.main' has no attribute 'theme'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.6/asyncio/events.py", line 126, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 222, in <lambda>
    self._task.add_done_callback(lambda task: self._catch_exceptions(task.result))
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 241, in _catch_exceptions
    self._finish(success=False, exception=exc)
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 259, in _finish
    self.on_error(self.exception)
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 496, in handle_exc
    raise exc
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 229, in _catch_exceptions
    success = callabee(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/stig/commands/base/config.py", line 80, in run
    setting.set(val)
  File "/usr/lib/python3.6/site-packages/stig/settings/settings.py", line 121, in set
    self.__on_change.send(self)
  File "/usr/lib/python3.6/site-packages/blinker/base.py", line 267, in send
    for receiver in self.receivers_for(sender)]
  File "/usr/lib/python3.6/site-packages/blinker/base.py", line 267, in <listcomp>
    for receiver in self.receivers_for(sender)]
  File "/usr/lib/python3.6/site-packages/stig/tui/hooks.py", line 58, in _set_theme
    except tui.theme.ThemeError as e:
AttributeError: module 'stig.tui.main' has no attribute 'theme'

Feature request: creating torrents

It would be cool if stig supported creating new .torrent files via a CLI command, for example:

stig create -o asd.torrent -i ./asd/*.dat --chunk-size 256K --tracker example.com

To keep things simple, it could just create the .torrent file in the designated path, then the user would have to add it manually (possibly supplying the path to the data and manually issuing a recheck).
The paths put into the torrent could be relative to the CWD for maximum flexibility.
--chunk-size could be parsed with humanfriendly.

Missing building instructions

Python is not my thing so I have to do a bit of guesswork and it would be great to have some guidance on how to build and run stig without wasting too much time/effort doing all what you've already done on your side.

Any chance also to get some binary package for common distros ?

[Enhancement] Possibility of named tabs

It would be nice to can assign names to tabs.
For example:

tab "stopped&to-be-deleted" ls stopped&path~borrar --sort !ratio --columns name,size,ratio
tab "Descargados" ls path~borrar --sort !ratio --columns name,size,ratio

The text between quotes would be the tab title.

Release v0.7.2a only have version/changelog changes

Hi!

Is v0.7.2a supposed to only have the changelog and version bump changes? It should include 4ea6c2f right?

diff -Naur stig-0.7.1a/CHANGELOG stig-0.7.2a/CHANGELOG
--- stig-0.7.1a/CHANGELOG       2017-06-09 10:35:03.000000000 -0300
+++ stig-0.7.2a/CHANGELOG       2017-06-12 08:47:31.000000000 -0300
@@ -1,3 +1,8 @@
+2017-06-12 0.7.2a
+  Fixed bugs:
+    * 'peerlist' command crashed with a NameError if no title was specified
+
+
 2017-06-09 0.7.1a
   Fixed bugs:
     * Pressing <page up> or <page down> with a modifier (namely <alt>) resulted
diff -Naur stig-0.7.1a/stig/version.py stig-0.7.2a/stig/version.py
--- stig-0.7.1a/stig/version.py 2017-06-09 10:35:03.000000000 -0300
+++ stig-0.7.2a/stig/version.py 2017-06-12 08:47:31.000000000 -0300
@@ -1 +1 @@
-__version__ = '0.7.1a'
+__version__ = '0.7.2a'

stig only refresh transmission information on a 60s timeout

Related to #54. Using aiohttp 3.0.1, on Arch Linux, with either v0.8.2a or the current HEAD.

I'm getting a strange behaviour that stig only update the transmission information (speed, progress, activity, etc.) every 60s. I think this was introduced on 6eaedb6. I manually timed the refreshes and changing the timeout=60 to timeout=n I get refreshes every n seconds.

Typo in `default.theme`

In stig/settings/default.theme the foreground colors use $list_bg instead of $name.stopped_fg

index a354f08..bd97431 100644
--- i/stig/settings/default.theme
+++ w/stig/settings/default.theme
@@ -180,12 +180,12 @@ torrentlist.name.queued.complete.unfocused         $name.queued_fg           on
 torrentlist.name.queued.complete.focused           $name.queued_fg           on $list_bg.f

 $name.stopped_fg = dark gray
-torrentlist.name.stopped.progress1.unfocused       $list_bg.f,underline  on $list_bg.uf
-torrentlist.name.stopped.progress1.focused         $list_bg.uf,underline on $list_bg.f
-torrentlist.name.stopped.progress2.unfocused       $list_bg.f            on $list_bg.uf
-torrentlist.name.stopped.progress2.focused         $list_bg.uf           on $list_bg.f
-torrentlist.name.stopped.complete.unfocused        $list_bg.f            on $list_bg.uf
-torrentlist.name.stopped.complete.focused          $list_bg.uf           on $list_bg.f
+torrentlist.name.stopped.progress1.unfocused       $name.stopped_fg,underline on $list_bg.uf
+torrentlist.name.stopped.progress1.focused         $name.stopped_fg,underline on $list_bg.f
+torrentlist.name.stopped.progress2.unfocused       $name.stopped_fg           on $list_bg.uf
+torrentlist.name.stopped.progress2.focused         $name.stopped_fg           on $list_bg.f
+torrentlist.name.stopped.complete.unfocused        $name.stopped_fg           on $list_bg.uf
+torrentlist.name.stopped.complete.focused          $name.stopped_fg           on $list_bg.f

 $name.verifying_fg = yellow
 torrentlist.name.verifying.progress1.unfocused     $name.verifying_fg,underline on $list_bg.uf

Set tmux title to "stig"

Currently, title would be Python which is ugly. You can set the tmux title to stig with this escape sequences.

printf '\033k%s\033\\' 'stig'

This code only works if allow-rename option in tmux set to on, default is off. You can set this in tmux.conf.

set-option -g allow-rename on

Also, there is a environment variable $TMUX that you can check if tmux is open.

ranger provides an option for that, maybe you can provide too. But actually, I don't think extra flag is necessary, since if you set that tmux option to on, this will be what you expected.

Silly undocumented RC path on macOS

On macOS, stig tries to read its RC file from ~/Library/Application Support/stig/rc. Since stig uses appdirs to generate config file paths, I assume this behavior is intentional.

Besides the macOS config path being annoyingly long to type, it would be much saner if stig tried to read ~/.config/stig/rc first and ~/Library/Application Support/stig/rc was a fallback if used at all. I spent a disappointing amount of time trying to find out why stig was trying to connect to localhost despite srv.url being set in ~/.config/stig/rc and only found out it wasn't reading that file because I lowered the default logging level in logging.py.

Error when starting first time

Hi,

I have this error when I'm starting first ime

Traceback (most recent call last):
  File "/usr/local/bin/stig", line 11, in <module>
    load_entry_point('stig==0.4.0a0', 'console_scripts', 'stig')()
  File "/usr/local/lib/python3.4/dist-packages/stig/__init__.py", line 16, in run
    from . import main
  File "/usr/local/lib/python3.4/dist-packages/stig/main.py", line 19, in <module>
    cliargs, clicmds = cliopts.parse()
  File "/usr/local/lib/python3.4/dist-packages/stig/cliopts.py", line 89, in parse
    from .commands import is_op
  File "/usr/local/lib/python3.4/dist-packages/stig/commands/__init__.py", line 287
    async def wait_async(self):
            ^
SyntaxError: invalid syntax

crash when marking files

When I use space to mark files, stig immediately crashes with the following error message

Traceback (most recent call last):
  File "/usr/bin/stig", line 11, in <module>
    load_entry_point('stig==0.4.0a0', 'console_scripts', 'stig')()
  File "/usr/lib/python3.6/site-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/usr/lib/python3.6/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/usr/lib/python3.6/site-packages/stig/tui/main.py", line 148, in run
    urwidloop.run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 45, in run
    raise self._exc_info
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 563, in run_async
    self._maybe_run_callbacks(process, on_success, on_error)
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 509, in _maybe_run_callbacks
    raise exc
  File "/usr/lib/python3.6/site-packages/stig/commands/__init__.py", line 240, in _catch_exceptions
    success = callabee(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/stig/commands/tui/tui.py", line 175, in run
    widget.mark(toggle=toggle, all=all)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 322, in mark
    self._set_mark(True, toggle=toggle, all=all)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 363, in _set_mark
    mark_leaves(self._listbox.focus_position, mark)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 343, in mark_leaves
    get_widget(pos).is_marked = mark
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 340, in get_widget
    return self._listbox.contents[pos][0].original_widget
TypeError: 'method' object is not subscriptable

I'm using Arch Linux.

Bad config example in README

Arch Linux
stig-git (installed from AUR package today)

In README there is the next config example: set tlist.columns name ratio rate-up rate-down but it fails to me: Unknown setting: tlist.columns

How can I define the default columns (and sort) to show in TUI?

ImportError: cannot import name 'Timeout'

I've just updated ArchLinux and aiohttp was updated, after that when starting stig I get:

Traceback (most recent call last):
  File "/usr/bin/stig", line 11, in <module>
    load_entry_point('stig==0.8.1a0', 'console_scripts', 'stig')()
  File "/usr/lib/python3.6/site-packages/stig/__init__.py", line 16, in run
    from . import main
  File "/usr/lib/python3.6/site-packages/stig/main.py", line 27, in <module>
    from . import settings
  File "/usr/lib/python3.6/site-packages/stig/settings/__init__.py", line 13, in <module>
    from .types_srv import is_srv_setting
  File "/usr/lib/python3.6/site-packages/stig/settings/types_srv.py", line 18, in <module>
    from ..client.errors import ClientError
  File "/usr/lib/python3.6/site-packages/stig/client/__init__.py", line 19, in <module>
    from .utils import Response
  File "/usr/lib/python3.6/site-packages/stig/client/utils.py", line 35, in <module>
    from aiohttp import Timeout as AsyncIOTimeout
ImportError: cannot import name 'Timeout'

division by zero

I keep getting division by zero; yes I have various torrents that haven't started, and so.

Traceback (most recent call last):
  File "/usr/bin/stig", line 11, in <module>
    load_entry_point('stig==0.7.3a0', 'console_scripts', 'stig')()
  File "/usr/lib/python3.6/site-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/usr/lib/python3.6/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/usr/lib/python3.6/site-packages/stig/tui/main.py", line 212, in run
    urwidloop.run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 56, in run
    raise self._exc_info
  File "/usr/lib/python3.6/asyncio/events.py", line 127, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 1289, in faux_idle_callback
    callback()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 564, in entering_idle
    self.draw_screen()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 578, in draw_screen
    canvas = self._topmost_widget.render(self.screen_size, focus=True)
  File "/usr/lib/python3.6/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3.6/site-packages/urwid/widget.py", line 1750, in render
    canv = get_delegate(self).render(size, focus=focus)
  File "/usr/lib/python3.6/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3.6/site-packages/urwid/container.py", line 1526, in render
    canv = w.render((maxcol, rows), focus=focus and item_focus)
  File "/usr/lib/python3.6/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3.6/site-packages/stig/tui/tabs.py", line 129, in render
    canvas = current_widget.render(size_content, focus)
  File "/usr/lib/python3.6/site-packages/urwid/widget.py", line 141, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/tlist.py", line 116, in render
    self._update_listitems()
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/tlist.py", line 149, in _update_listitems
    walker.append(widgetcls(tdict[tid], row))
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/tlist.py", line 34, in __init__
    self.update(torrent)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/tlist.py", line 41, in update
    widget.update(torrent)
  File "/usr/lib/python3.6/site-packages/stig/tui/torrent/__init__.py", line 88, in update
    self.data.update(data)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/torrent.py", line 388, in __getitem__
    value = _MODIFY[key](raw)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/torrent.py", line 324, in <lambda>
    '%uploaded'         : lambda raw: raw['uploadedEver'] / raw['totalSize'] * 100,
ZeroDivisionError: division by zero

stig.client.errors.AuthError: Authentication failed

Authentication is not handled nicely :

Traceback (most recent call last):
  File "/usr/local/bin/stig", line 11, in <module>
    load_entry_point('stig==0.0.1a0', 'console_scripts', 'stig')()
  File "/usr/local/lib/python3.5/dist-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/usr/local/lib/python3.5/dist-packages/stig/main.py", line 111, in run
    if not tui.run(cmdcache.rccmds + cmdcache.clicmds):
  File "/usr/local/lib/python3.5/dist-packages/stig/tui/main.py", line 130, in run
    aioloop.run_until_complete(srvapi.stop_polling())
  File "/usr/lib/python3.5/asyncio/base_events.py", line 466, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/api.py", line 189, in stop_polling
    await poller.stop()
  File "/usr/local/lib/python3.5/dist-packages/stig/client/poll.py", line 156, in stop
    await asyncio.wait_for(self._poll_loop_task, timeout=0, loop=self.loop)
  File "/usr/lib/python3.5/asyncio/tasks.py", line 400, in wait_for
    return fut.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/local/lib/python3.5/dist-packages/stig/tui/main.py", line 127, in run
    urwidloop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/local/lib/python3.5/dist-packages/stig/tui/urwidpatches.py", line 45, in run
    raise self._exc_info
  File "/usr/lib/python3.5/asyncio/events.py", line 126, in _run
    self._callback(*self._args)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/poll.py", line 73, in reraise
    task.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/poll.py", line 85, in _poll_loop
    await self._poll_task
  File "/usr/lib/python3.5/asyncio/futures.py", line 380, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 304, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/api_torrent.py", line 167, in _get_torrents_by_ids
    raw_tlist = await self.rpc.torrent_get(fields=fields)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 384, in request
    await self.connect()
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 224, in connect
    raise self.__connect_exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/poll.py", line 114, in _do_poll
    response = await self._request()
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 384, in request
    await self.connect()
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 224, in connect
    raise self.__connect_exception
  File "/usr/local/lib/python3.5/dist-packages/stig/tui/hooks.py", line 21, in coro
    await srvapi.rpc.connect(url.value)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 266, in connect
    info = await self.__send_request(test_request)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 347, in __send_request
    answer = await self.__post(post_data)
  File "/usr/local/lib/python3.5/dist-packages/stig/client/aiotransmission/rpc.py", line 323, in __post
    raise AuthError(str(self.url))
stig.client.errors.AuthError: Authentication failed: localhost
Exception ignored in: <bound method RequestPoller.__del__ of <RequestPoller TorrentAPI.torrents(torrents=None, keys=('rate-up', '%verified', 'ratio', 'name', 'rate-down', 'status', 'size-downloaded', 'peers-connected', 'timespan-eta', '%downloaded', 'size-uploaded', 'isolated', 'peers-seeding', '%metadata', 'size-final'))>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/stig/client/poll.py", line 165, in __del__
RuntimeError: You forgot to call stop() on <RequestPoller TorrentAPI.torrents(torrents=None, keys=('rate-up', '%verified', 'ratio', 'name', 'rate-down', 'status', 'size-downloaded', 'peers-connected', 'timespan-eta', '%downloaded', 'size-uploaded', 'isolated', 'peers-seeding', '%metadata', 'size-final'))>
Task was destroyed but it is pending!
task: <Task pending coro=<RequestPoller._poll_loop() running at /usr/local/lib/python3.5/dist-packages/stig/client/poll.py:98> wait_for=<Future pending cb=[Task._wakeup()]> cb=[RequestPoller.start.<locals>.reraise() at /usr/local/lib/python3.5/dist-packages/stig/client/poll.py:69]>
Task was destroyed but it is pending!
task: <Task pending coro=<API._manage_pollers() running at /usr/local/lib/python3.5/dist-packages/stig/client/api.py:139> wait_for=<Future pending cb=[Task._wakeup()]>>

Question about adding torrents

Is there a way to change the location a torrent will be saved to? Most of what I download go in the default location but a select few need to go in another location.

Also, when adding is there a way to rename it?

Feature request: global statistics

Many clients offer global statistics and it would be nice if stig could support these as well.

I'm mostly interested in these:

  • All time upload
  • All time download
  • Global ratio

Here's what qBittorrent offers:

If transmission doesn't track all time stats, one could aggregate just the current stats basing on the active torrents and perhaps put that information under stig ls.

TimeoutError crash on connection loss

Steps To Reproduce

  1. Run stig and let it connect to a server
  2. Interrupt the connection by some means (I simply turned off WiFi)
  3. Wait for stig to crash due to an unhandled TimeoutError
Traceback (most recent call last):
  File "/Users/tobias/.virtualenvs/stig/bin/stig", line 11, in <module>
    load_entry_point('stig==0.7.3a0', 'console_scripts', 'stig')()
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/stig-0.7.3a0-py3.6.egg/stig/__init__.py", line 17, in run
    main.run()
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/stig-0.7.3a0-py3.6.egg/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/stig-0.7.3a0-py3.6.egg/stig/tui/main.py", line 212, in run
    urwidloop.run()
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/urwid-1.3.1-py3.6-macosx-10.12-x86_64.egg/urwid/main_loop.py", line 278, in run
    self._run()
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/urwid-1.3.1-py3.6-macosx-10.12-x86_64.egg/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/Users/tobias/.virtualenvs/stig/lib/python3.6/site-packages/stig-0.7.3a0-py3.6.egg/stig/tui/urwidpatches.py", line 56, in run
    raise self._exc_info
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/selector_events.py", line 724, in _read_ready
    data = self._sock.recv(self.max_size)
TimeoutError: [Errno 60] Operation timed out

The crash can be prevented by changing line 40 of stig/tui/urwidpatches.py to:

        if exc and not isinstance(exc, TimeoutError):

This prevents the crash, and stig connects to the server just fine when the connection is restored. This isn't exactly a fix of course, but I'm not sure how or where the exception ought to be dealt with.

aiohttp update breakage

stig stopped working on Arch after an update a couple of days ago.
Here's the output:

$ stig
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/stig/tui/main.py", line 153, in run
    urwidloop.run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 45, in run
    raise self._exc_info
  File "/usr/lib/python3.6/asyncio/events.py", line 127, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.6/site-packages/stig/client/poll.py", line 73, in reraise
    task.result()
  File "/usr/lib/python3.6/site-packages/stig/client/poll.py", line 85, in _poll_loop
    await self._poll_task
  File "/usr/lib/python3.6/site-packages/stig/client/poll.py", line 114, in _do_poll
    response = await self._request()
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 297, in torrents
    return await self._get_torrents_by_ids(keys, autoconnect=autoconnect)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 211, in _get_torrents_by_ids
    response = await self._request_torrents(fields, ids)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 168, in _request_torrents
    raw_tlist = await self.rpc.torrent_get(fields=fields)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 393, in request
    return await self.__send_request(rpc_request)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 347, in __send_request
    answer = await self.__post(post_data)
  File "/usr/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 307, in __post
    response = await self.__session.post(repr(self.__url), data=data, headers=self.__headers)
  File "/usr/lib/python3.6/site-packages/aiohttp/client.py", line 631, in __await__
    resp = yield from self._coro
  File "/usr/lib/python3.6/site-packages/aiohttp/client.py", line 230, in _request
    conn = yield from self._connector.connect(req)
  File "/usr/lib/python3.6/site-packages/aiohttp/connector.py", line 385, in connect
    self._acquired.remove(placeholder)
KeyError: <aiohttp.connector._TransportPlaceholder object at 0x7f77d39fb390>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/stig", line 11, in <module>
    load_entry_point('stig==0.4.1a0', 'console_scripts', 'stig')()
  File "/usr/lib/python3.6/site-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/usr/lib/python3.6/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/usr/lib/python3.6/site-packages/stig/tui/main.py", line 156, in run
    aioloop.run_until_complete(srvapi.stop_polling())
  File "/usr/lib/python3.6/asyncio/base_events.py", line 464, in run_until_complete
    raise RuntimeError('Event loop stopped before Future completed.')
RuntimeError: Event loop stopped before Future completed.

python related stuff from my pacman.log:

[2017-06-02 22:51] [ALPM] upgraded python-setuptools (1:35.0.2-1 -> 1:36.0.1-1)
[2017-06-02 22:51] [ALPM] upgraded python-chardet (3.0.2-1 -> 3.0.3-1)
[2017-06-02 22:51] [ALPM] upgraded python-multidict (2.1.4-1 -> 2.1.6-1)
[2017-06-02 22:51] [ALPM] upgraded python-async-timeout (1.2.0-2 -> 1.2.1-2)
[2017-06-02 22:51] [ALPM] upgraded python-yarl (0.9.8-1 -> 0.10.2-2)
[2017-06-02 22:51] [ALPM] upgraded python-aiohttp (1.3.1-1 -> 2.1.0-1)

Nothing else relevant was upgraded as far as I can tell.
python-aiohttp is the only stig dependency here and it was mentioned in the error output, so I guess that's the problem.

crash when missing metadata

After adding a magnet link, it seems to take a while to load the metadata of the torrent. If it did not load the metadata yet and you try to inspect the contents of the torrent in stig, stig crashes.
Here is the stack trace of the crash:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 122, in _do_poll
    self._run_callbacks(response=response)
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 130, in _run_callbacks
    self._on_response.send(response)
  File "/usr/local/lib/python3.6/site-packages/blinker/base.py", line 267, in send
    for receiver in self.receivers_for(sender)]
  File "/usr/local/lib/python3.6/site-packages/blinker/base.py", line 267, in <listcomp>
    for receiver in self.receivers_for(sender)]
  File "/usr/local/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 223, in _handle_response
    self._init_listitems(response.torrents)
  File "/usr/local/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 232, in _init_listitems
    self._table, self._ffilter)
  File "/usr/local/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 76, in init
    forest = self._create_file_forest(torrents)
  File "/usr/local/lib/python3.6/site-packages/stig/tui/torrent/flist.py", line 128, in _create_file_forest
    rootnodename = next(iter(filetree.keys()))
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/bin/stig", line 11, in <module>
    sys.exit(run())
  File "/usr/local/lib/python3.6/site-packages/stig/init.py", line 17, in run
    main.run()
  File "/usr/local/lib/python3.6/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/usr/local/lib/python3.6/site-packages/stig/tui/main.py", line 151, in run
    aioloop.run_until_complete(srvapi.stop_polling())
  File "/usr/local/Cellar/python3/3.6.0_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 466, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.6/site-packages/stig/client/api.py", line 225, in stop_polling
    await poller.stop()
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 155, in stop
    await asyncio.wait_for(self._poll_loop_task, timeout=0, loop=self.loop)
  File "/usr/local/Cellar/python3/3.6.0_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py", line 352, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.6/site-packages/stig/tui/main.py", line 148, in run
    urwidloop.run()
  File "/usr/local/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/local/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/local/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 45, in run
    raise self._exc_info
  File "/usr/local/Cellar/python3/3.6.0_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/events.py", line 126, in _run
    self._callback(*self._args)
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 73, in reraise
    task.result()
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 85, in _poll_loop
    await self._poll_task
RuntimeError: coroutine raised StopIteration

RuntimeWarning: coroutine 'ClientSession.close' was never awaited/Unclosed client session

This is related to #54. Using Arch Linux aiohttp 3.0.1.

This happen with either the v0.8.2a or on c28fd6b, log from c28fd6b is:

❯ stig add *.torrent      
Torrent already exists: ***
/usr/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py:71: RuntimeWarning: coroutine 'ClientSession.close' was never awaited
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f2accf7ba58>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7f2acb71f9e8>, 362141.441238972)]']
connector: <aiohttp.connector.TCPConnector object at 0x7f2accf7b940>

I don't understand asyncio very well, but I think that there is two bugs here. I can 'fix' (???) the RuntimeWarning by using

--- i/stig/client/aiotransmission/rpc.py
+++ w/stig/client/aiotransmission/rpc.py
@@ -68,7 +68,7 @@ class TransmissionRPC():
     def __del__(self, _warnings=warnings):
         if self._session is not None and not self._session.closed:
             _warnings.warn('disconnect() wasn\'t called', ResourceWarning)
-            self._session.close()
+            asyncio.ensure_future(self._session.close())
 
     def on(self, signal, callback, autoremove=True):
         """

But I still get the Unclosed client session/Unclosed connector.

Handle the KeyboardInterrupt exception

Steps: open stig and press C-c.

~
❯ stig
Traceback (most recent call last):
  File "/usr/bin/stig", line 11, in <module>
    load_entry_point('stig==0.7.3a0', 'console_scripts', 'stig')()
  File "/usr/lib/python3.6/site-packages/stig/__init__.py", line 17, in run
    main.run()
  File "/usr/lib/python3.6/site-packages/stig/main.py", line 119, in run
    if not tui.run(run_commands):
  File "/usr/lib/python3.6/site-packages/stig/tui/main.py", line 212, in run
    urwidloop.run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 54, in run
    self._loop.run_forever()
  File "/usr/lib/python3.6/asyncio/base_events.py", line 421, in run_forever
    self._run_once()
  File "/usr/lib/python3.6/asyncio/base_events.py", line 1390, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/lib/python3.6/selectors.py", line 445, in select
    fd_event_list = self._epoll.poll(timeout, max_ev)
KeyboardInterrupt

Would be nice if as most all other programs, we can exit with C-c (SIGINT interrupt signal).
Since are you using a asyncio loop, you could just attach the sigint to finish the program as I did here using the signal module of stdlib.

Provide .desktop file

Hello !
So, I've been thinking of adding a .desktop entry for stig, for linux systems. This would allow two things :
This first would be to be able to launch stig from a desktop shortcut or a launcher, if your DE/WM gives you this.
The second (and most useful, IMO), would be to have hooks on magnet links and torrent files, so that, when downloading a torrent file, you can add it instantly via stig, instead of having to store it somewhere, and then lauch your terminal, and then do the "stig add...". This would also let you double-click on a .torrent file, if you have a file explorer, and it would add it automatically.
I can research it a bit more tomorrow, does this interest you ? The change would be to add a .desktop file to the project, and add a line to the setup.py file, to put the desktop entry under /usr/share/applications

No stig command after installation

No matter if I install it globally or locally, it can't find the stig command. I'm using latest stable Debian.
I tried installing with --user option first, then from the latest github branch and finally globally but same results

$ sudo pip3 install stig
[sudo] password for hiru:
Requirement already satisfied: stig in /root/.local/lib/python3.5/site-packages
Requirement already satisfied: urwid>=1.3.0 in /root/.local/lib/python3.5/site-packages (from stig)
Requirement already satisfied: urwidtrees>=1.0.3dev0 in /root/.local/lib/python3.5/site-packages (from stig)
Requirement already satisfied: natsort in /root/.local/lib/python3.5/site-packages (from stig)
Requirement already satisfied: pyxdg in /usr/lib/python3/dist-packages (from stig)
Requirement already satisfied: blinker in /root/.local/lib/python3.5/site-packages (from stig)
Requirement already satisfied: aiohttp>=0.22.5 in /root/.local/lib/python3.5/site-packages (from stig)
Requirement already satisfied: mock in /root/.local/lib/python3.5/site-packages (from urwidtrees>=1.0.3dev0->stig)
Requirement already satisfied: yarl>=0.11 in /root/.local/lib/python3.5/site-packages (from aiohttp>=0.22.5->stig)
Requirement already satisfied: multidict>=3.0.0 in /root/.local/lib/python3.5/site-packages (from aiohttp>=0.22.5->stig)
Requirement already satisfied: chardet in /usr/lib/python3/dist-packages (from aiohttp>=0.22.5->stig)
Requirement already satisfied: async-timeout>=1.2.0 in /root/.local/lib/python3.5/site-packages (from aiohttp>=0.22.5->stig)
Requirement already satisfied: pbr>=0.11 in /root/.local/lib/python3.5/site-packages (from mock->urwidtrees>=1.0.3dev0->stig)
Requirement already satisfied: six>=1.9 in /usr/lib/python3/dist-packages (from mock->urwidtrees>=1.0.3dev0->stig)
Requirement already satisfied: idna>=2.0 in /usr/lib/python3/dist-packages (from yarl>=0.11->aiohttp>=0.22.5->stig)

$ stig
-bash: stig: command not found

Unformatted tabs on Arch

I copied the config file in the README but I have unformatted parameters in the tabs. It looks different from the screenshot in the README and in particular the lines

!progress,path,!rate
!progress --columns name,progress,ratio,size

are parsed literally showing {!progress,path,!rate} and {!progress} in the title.

I'm on Arch and I installed stig from the AUR

configuration dir and file not created when not there

On first run, stig could/should create a dummy configuration file and all needed path. It doesn't for now.

Also, please note that $HOME/.config/stig/rc is rather unusual, '.config' is far too much generic name and it should be '.stig' (you may take a look at the FHS for such choice).

Implement support for download/upload queues

Sorry if I open an issue just for this question but: how do I sort torrents using the queue order?

available choices are: activity, added, completed, created, downloaded, eta, name, path, peers, progress, rate, rate-down, rate-up, ratio, seeds, size, started, status, tracker, uploaded

but I can't see queue

Login and ssl support

Hi,
I've been looking for a replacement to transmission-remote-cli, and stig looks promising enough, but I still need ssl and login support for it to fit my needs.
I'm ready to contribute to the project to bring these features, but I'd need few pointers on where to start looking.

Cheers,
Alexandre.

How would I go about configuring ?

Transmission has always been confusing for me because certain daemon settings are replicated in client configuration and it's really not clear at all how it's best to handle stuff. I see this does not depend on transmission but I assume it requires transmission-cli daemon right and it will respect it's settings ?

AttributeError: 'TransmissionURL' object has no attribute 'username'

When trying to run stig 0.8.0a with the following config:

set srv.url https://rpc:[email protected]/transmission/rpc/

… stig fails to start and prints these tracebacks:

Task exception was never retrieved
future: <Task finished coro=<_connect_to_new_url.<locals>.coro() done, defined at /usr/local/lib/python3.6/site-packages/stig/tui/hooks.py:30> exception=AttributeError("'TransmissionURL' object has no attribute 'username'",)>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/stig/tui/hooks.py", line 32, in coro
    await srvapi.rpc.connect(url.value)
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 202, in connect
    session_args['auth'] = aiohttp.BasicAuth(self.__url.username,
AttributeError: 'TransmissionURL' object has no attribute 'username'
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/stig/tui/main.py", line 186, in run
    urwidloop.run()
  File "/usr/local/lib/python3.6/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/local/lib/python3.6/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/local/lib/python3.6/site-packages/stig/tui/urwidpatches.py", line 93, in run
    raise self._exc_info
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/events.py", line 127, in _run
    self._callback(*self._args)
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 77, in reraise
    task.result()
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 87, in _poll_loop
    await self._poll_task
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 116, in _do_poll
    response = await self._request()
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 365, in torrents
    return await self._get_torrents_by_ids(keys)
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 274, in _get_torrents_by_ids
    response = await self._request_torrents(fields, ids)
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/api_torrent.py", line 233, in _request_torrents
    raw_tlist = await self.rpc.torrent_get(fields=fields)
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 344, in request
    await self.connect()
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 202, in connect
    session_args['auth'] = aiohttp.BasicAuth(self.__url.username,
AttributeError: 'TransmissionURL' object has no attribute 'username'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/stig", line 11, in <module>
    sys.exit(run())
  File "/usr/local/lib/python3.6/site-packages/stig/__init__.py", line 22, in run
    main.run()
  File "/usr/local/lib/python3.6/site-packages/stig/main.py", line 155, in run
    if not tui.run(run_commands):
  File "/usr/local/lib/python3.6/site-packages/stig/tui/main.py", line 189, in run
    aioloop.run_until_complete(srvapi.stop_polling())
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.6/site-packages/stig/client/api.py", line 218, in stop_polling
    await poller.stop()
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/api_status.py", line 36, in stop
    await self._poller_stats.stop(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 157, in stop
    await asyncio.wait_for(self._poll_loop_task, timeout=0, loop=self.loop)
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
    return fut.result()
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/events.py", line 127, in _run
    self._callback(*self._args)
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 77, in reraise
    task.result()
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 87, in _poll_loop
    await self._poll_task
  File "/usr/local/lib/python3.6/site-packages/stig/client/poll.py", line 116, in _do_poll
    response = await self._request()
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 344, in request
    await self.connect()
  File "/usr/local/lib/python3.6/site-packages/stig/client/aiotransmission/rpc.py", line 202, in connect
    session_args['auth'] = aiohttp.BasicAuth(self.__url.username,
AttributeError: 'TransmissionURL' object has no attribute 'username'

Throw error message when binding invalid keys like <shift-enter>

I want to change the default binding of alt-enter showing the files of a torrent to shift-enter but I can't get it to work.
I put the following in my rc file

unbind 'alt-enter'
bind shift-enter tab lsf

I'm not sure whether I should use apostrophes or not (like that: 'shift-enter'), anyway none of the options worked.

[Question] Line based colouring

Sorry for the lazy question, I'm still using rtorrent and only considering switching to transmission with stig. I only saw the screenshot in the README and wondered if it's possible to have more "traditional" line-based colours: everything white or gray, green for active torrents, yellow for paused, red for stopped; this kind of thing.

Option to change keybindings through settings file

Hi!

I have a small issue with the new change that alt-enter opens the file list. I use OS X and Terminal.app, and the alt key isn't used be default. I could enable it, but that would mess up the rest of my workflow (I'm used to alt not being alt :)).

So it would be great if I could specify my own keybindings somehow.
There is other keybindings I would like to change as well, so it's not only for my alt-key laziness/problem :)

I could look into this myself, but not sure how you would like the syntax for keybindings to be.

Maybe something like this?

set tui.bind 'context:torrent' 'key:alt-enter' 'action:tab filelist'

Missing dependency urwidtrees

First of all, very cool project! transmission-remote-cli kept crashing for me, but this looks really nice.

Looks like you're missing the dependency urwidtrees in your setup and that leads to crashes. I fixed it myself in my virtualenv with pip install urwidtrees.

Missing dependency : setuptools

I've tried to run stig on a RaspBerry Pi 3 with Raspbian and these packages are at least needed

python3-urwid python3-aiohttp python3-blinker python3-appdirs python3-setuptools

setuptools is not listed in the requirements.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.