Release 4.1.8 (#645)

* 4.1.8-develop1

* Bump humanize from 4.9.0 to 4.10.0 (#603)

Bumps [humanize](https://github.com/python-humanize/humanize) from 4.9.0 to 4.10.0.
- [Release notes](https://github.com/python-humanize/humanize/releases)
- [Commits](https://github.com/python-humanize/humanize/compare/4.9.0...4.10.0)

---
updated-dependencies:
- dependency-name: humanize
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Print the schedule and delay before starting the sleep (#606)

* Bump croniter from 2.0.5 to 2.0.7 (#607)

Bumps [croniter](https://github.com/kiorky/croniter) from 2.0.5 to 2.0.7.
- [Changelog](https://github.com/kiorky/croniter/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/kiorky/croniter/compare/2.0.5...2.0.7)

---
updated-dependencies:
- dependency-name: croniter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump qbittorrent-api from 2024.5.63 to 2024.7.64 (#611)

Bumps [qbittorrent-api](https://github.com/rmartin16/qbittorrent-api) from 2024.5.63 to 2024.7.64.
- [Release notes](https://github.com/rmartin16/qbittorrent-api/releases)
- [Changelog](https://github.com/rmartin16/qbittorrent-api/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rmartin16/qbittorrent-api/compare/v2024.5.63...v2024.7.64)

---
updated-dependencies:
- dependency-name: qbittorrent-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Check for symlinks prior to counting file as a hardlink (#609)

* Bump croniter from 2.0.7 to 3.0.1 (#617)

* Update SUPPORTED_VERSIONS.json (#618)

* Update SUPPORTED_VERSIONS.json (#612)

Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com>

* Bump croniter from 3.0.1 to 3.0.3 (#621)

Bumps [croniter](https://github.com/kiorky/croniter) from 3.0.1 to 3.0.3.
- [Changelog](https://github.com/kiorky/croniter/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/kiorky/croniter/compare/3.0.1...3.0.3)

---
updated-dependencies:
- dependency-name: croniter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump pre-commit from 3.7.1 to 3.8.0 (#620)

Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.7.1 to 3.8.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.7.1...v3.8.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: bump required python version to 3.9.0+ (#623)

* Typo fix in `  docs/Config-Setup.md` (#627)

* Typo fix in `config.yml.sample` (#626)

* Bump flake8 from 7.1.0 to 7.1.1 (#628)

Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.0 to 7.1.1.
- [Commits](https://github.com/pycqa/flake8/compare/7.1.0...7.1.1)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(docs): Sync wiki to docs [skip-cd]

* Bump qbittorrent-api from 2024.7.64 to 2024.8.65 (#637)

Bumps [qbittorrent-api](https://github.com/rmartin16/qbittorrent-api) from 2024.7.64 to 2024.8.65.
- [Release notes](https://github.com/rmartin16/qbittorrent-api/releases)
- [Changelog](https://github.com/rmartin16/qbittorrent-api/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rmartin16/qbittorrent-api/compare/v2024.7.64...v2024.8.65)

---
updated-dependencies:
- dependency-name: qbittorrent-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update SUPPORTED_VERSIONS.json (#639)

* Extend logging to explain why torrent files were not deleted. (#640)

* Extend logging to explain why torrent files were not deleted.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* update tox

* Add force_auto_tmm_ignore_tags feature (#634)

* Add force_auto_tmm_ignore_tags feature to qbittorrent module
This commit introduces a new configuration option 'force_auto_tmm_ignore_tags' that allows users to specify tags which will prevent the force_auto_tmm feature from being applied to that torrent.

Changes:

qbittorrent.py:
Modified the get_torrent_info method in the Qbt class
Added a check for matching tags to ignore when applying force_auto_tmm

config.py:
Added 'force_auto_tmm_ignore_tags' to the settings dictionary
Implemented check_for_attribute method call to load the new setting from config.yml

config.yml:
Added 'force_auto_tmm_ignore_tags' to the settings section
Included example tags 'cross-seed' and 'Upload' as default values to ignore

* remove extra spacing between lines.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix line length to adhere to flake8

* change log output for force_auto_tmm to multiline comment to adhere to flake8

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add comment explaining logic for ignoring force_auto_tmm using tags.

* Add force_auto_tmm_ignore_tags feature to qbittorrent module
This commit introduces a new configuration option 'force_auto_tmm_ignore_tags' that allows users to specify tags which will prevent the force_auto_tmm feature from being applied to that torrent.

Changes:

qbittorrent.py:
Modified the get_torrent_info method in the Qbt class
Added a check for matching tags to ignore when applying force_auto_tmm

config.py:
Added 'force_auto_tmm_ignore_tags' to the settings dictionary
Implemented check_for_attribute method call to load the new setting from config.yml

config.yml:
Added 'force_auto_tmm_ignore_tags' to the settings section
Included example tags 'cross-seed' and 'Upload' as default values to ignore

remove extra spacing between lines.

fix line length to adhere to flake8

[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

change log output for force_auto_tmm to multiline comment to adhere to flake8

[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

Add comment explaining logic for ignoring force_auto_tmm using tags.

* fixed text formatting so its displayed properly when script is run

* remove f-string

---------

Co-authored-by: TJZine <tzine@student.bridgew.edu>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com>

* Bump peter-evans/create-pull-request from 6 to 7 (#642)

Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6 to 7.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v6...v7)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* 4.1.8

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: bobokun <jon.cy.lee98@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ineednewpajamas <73252768+ineednewpajamas@users.noreply.github.com>
Co-authored-by: Nicholas Sereni <glicholas@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com>
Co-authored-by: James Tufarelli <8152401+Minituff@users.noreply.github.com>
Co-authored-by: Actionbot <actions@github.com>
Co-authored-by: darkeclipse <5069005+Dark3clipse@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Tristan Zine <72631199+TJZine@users.noreply.github.com>
Co-authored-by: TJZine <tzine@student.bridgew.edu>
This commit is contained in:
bakerboy448 2024-09-05 19:08:15 -05:00 committed by GitHub
parent 322ea1dd57
commit 87ffdda8c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 80 additions and 52 deletions

View file

@ -42,7 +42,7 @@ jobs:
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
commit-message: Update SUPPORTED_VERSIONS.json
title: "Update SUPPORTED_VERSIONS.json for ${{ github.event.inputs.targetBranch || github.ref_name }}"

View file

@ -1,16 +1,16 @@
# Requirements Updated
- qbittorrent-api==2024.8.65
- croniter==3.0.3
- humanize==4.10.0
# New Updates
- BHD config options are now deprecated due to qbm no longer needing to use the api to detect unregistered torrents (Closes #595)
- Updates mover script to add logging and default to completed torrents only with new optional argument (`--status-filter`)
- Adds `force_auto_tmm_ignore_tags` feature to ignore tags when force_auto_tmm is enabled (#634)
# Bug Fixes
- Adds new ignore message for unregistered torrents (Closes #592)
- Allow `max_seeding_time` to be unlimited (-1) if min_seeding_time is set (Closes #596)
- Fixes checking tracker status for udp/wss (Closes #586)
- Fixes Logging header not getting logged in every run (Closes #591)
- Fixes min_seeding_time tag removal when max_seeding_time is -1 (#Closes 598)
- Fixes Remove orphaned without moving to orphaned_dir (Closes #590)
- Fixes bug in printing schedule mode when run is set to True
- Modifies noHL threshold to 0.1 to address false positives
- Fixes Print the schedule and delay before starting the sleep (Closes [#605](https://github.com/StuffAnThings/qbit_manage/issues/605))
- Fixes noHL counting symlinks as part of its logic (Closes [#608](https://github.com/StuffAnThings/qbit_manage/issues/608))
- Fix typos in documentation (#627)
- Extended logging to explain why torrent files were not deleted (#625)
Special thanks to @bakerboy448, @ineednewpajamas, @lflare, @convexshiba for their contributions!
**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.1.6...v4.1.7
Special thanks to @ineednewpajamas, @glicholas, @Minituff, @Dark3clipse, @TJZine for their contributions!
**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.1.7...v4.1.8

View file

@ -1,8 +1,8 @@
FROM python:3.11-alpine
ARG BRANCH_NAME=master
ENV BRANCH_NAME ${BRANCH_NAME}
ENV TINI_VERSION v0.19.0
ENV QBM_DOCKER True
ENV BRANCH_NAME=${BRANCH_NAME}
ENV TINI_VERSION=v0.19.0
ENV QBM_DOCKER=True
COPY requirements.txt /

View file

@ -46,7 +46,7 @@ Generally expect new releases of Qbittorrent to not immediately be supported. Su
Check out the [wiki](https://github.com/StuffAnThings/qbit_manage/wiki) for installation help
1. Install qbit_manage either by installing Python 3.8.1+ on the localhost and following the [Local Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Local-Installations) Guide or by installing Docker and following the [Docker Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Docker-Installation) Guide or the [unRAID Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Unraid-Installation) Guide.
1. Install qbit_manage either by installing Python 3.9.0+ on the localhost and following the [Local Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Local-Installations) Guide or by installing Docker and following the [Docker Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Docker-Installation) Guide or the [unRAID Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Unraid-Installation) Guide.
1. Once installed, you have to [set up your Configuration](https://github.com/StuffAnThings/qbit_manage/wiki/Config-Setup) by create a [Configuration File](https://github.com/StuffAnThings/qbit_manage/blob/master/config/config.yml.sample) filled with all your values to connect to your qBittorrent instance.
1. Please refer to the list of [Commands](https://github.com/StuffAnThings/qbit_manage/wiki/Commands) that can be used with this tool.

View file

@ -1,10 +1,10 @@
{
"master": {
"qbit": "v4.6.5",
"qbitapi": "2024.5.63"
"qbit": "v4.6.6",
"qbitapi": "2024.8.65"
},
"develop": {
"qbit": "v4.6.5",
"qbitapi": "2024.5.63"
"qbit": "v4.6.6",
"qbitapi": "2024.8.65"
}
}

View file

@ -1 +1 @@
4.1.7
4.1.8

View file

@ -26,6 +26,9 @@ qbt:
settings:
force_auto_tmm: False # Will force qBittorrent to enable Automatic Torrent Management for each torrent.
force_auto_tmm_ignore_tags: #Torrents with these tags will be ignored when force_auto_tmm is enabled.
- cross-seed
- Upload
tracker_error_tag: issue # Will set the tag of any torrents that do not have a working tracker.
nohardlinks_tag: noHL # Will set the tag of any torrents with no hardlinks.
share_limits_tag: ~share_limit # Will add this tag when applying share limits to provide an easy way to filter torrents by share limit group/priority for each torrent
@ -36,7 +39,7 @@ settings:
cat_filter_completed: True # Filters for completed torrents only when running cat_update command
share_limits_filter_completed: True # Filters for completed torrents only when running share_limits command
tag_nohardlinks_filter_completed: True # Filters for completed torrents only when running tag_nohardlinks command
cat_update_all: True # Checks and udpates all torrent categories if set to True when running cat_update command, otherwise only update torrents that are uncategorized
cat_update_all: True # Checks and updates all torrent categories if set to True when running cat_update command, otherwise only update torrents that are uncategorized
directory:
# Do not remove these

View file

@ -46,6 +46,7 @@ This section defines any settings defined in the configuration.
| Variable | Definition | Default Values | Required |
| :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------| :----------------- | :----------------- |
| `force_auto_tmm` | Will force qBittorrent to enable Automatic Torrent Management for each torrent. | False | <center></center> |
| `force_auto_tmm_ignore_tags` | Torrents with these tags will be ignored when force_auto_tmm is enabled. | | <center></center> |
| `tracker_error_tag` | Define the tag of any torrents that do not have a working tracker. (Used in `--rem-unregistered` and `--tag-tracker-error`) | issue | <center></center> |
| `nohardlinks_tag` | Define the tag of any torrents that don't have hardlinks (Used in `--tag-nohardlinks`) | noHL | <center></center> |
| `share_limits_tag` | Will add this tag when applying share limits to provide an easy way to filter torrents by share limit group/priority for each torrent. For example, if you have a share-limit group `cross-seed` with a priority of 2 and the default share_limits_tag `~share_limits` would add the tag `~share_limit_2.cross-seed` (Used in `--share-limits`) | ~share_limit | <center></center> |

View file

@ -4,9 +4,9 @@ This wiki should tell you everything you need to know about the script to get it
## Getting Started
1. Install qbit_manage either by installing Python3.8.1+ on the localhost and following the [Local Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Local-Installations) Guide or by installing Docker and following the [Docker Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Docker-Installation) Guide or the [unRAID Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Unraid-Installation) Guide.<br>
2. Once installed, you have to [set up your Configuration](https://github.com/StuffAnThings/qbit_manage/wiki/Config-Setup) by create a [Configuration File](https://github.com/StuffAnThings/qbit_manage/blob/master/config/config.yml.sample) filled with all your values to connect to your qBittorrent instance.
3. Please refer to the list of [Commands](https://github.com/StuffAnThings/qbit_manage/wiki/Commands) that can be used with this tool.
1. Install qbit_manage either by installing Python3.9.0+ on the localhost and following the [Local Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Local-Installations) Guide or by installing Docker and following the [Docker Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Docker-Installation) Guide or the [unRAID Installation](https://github.com/StuffAnThings/qbit_manage/wiki/Unraid-Installation) Guide.<br>
1. Once installed, you have to [set up your Configuration](https://github.com/StuffAnThings/qbit_manage/wiki/Config-Setup) by create a [Configuration File](https://github.com/StuffAnThings/qbit_manage/blob/master/config/config.yml.sample) filled with all your values to connect to your qBittorrent instance.
1. Please refer to the list of [Commands](https://github.com/StuffAnThings/qbit_manage/wiki/Commands) that can be used with this tool.
## Support

View file

@ -1,6 +1,6 @@
# Local Installations
* Requires `python 3.8.1`. Dependencies must be installed by running:
* Requires `python 3.9.0`. Dependencies must be installed by running:
Navigate to the directory you'd liked to clone the repo into

View file

@ -13,7 +13,7 @@
- [settings](Config-Setup#settings)
- [directory](Config-Setup#directory)
- [cat](Config-Setup#cat)
- [cat_changes](Config-Setup#cat_changes)
- [cat_change](Config-Setup#cat_change)
- [tracker](Config-Setup#tracker)
- [nohardlinks](Config-Setup#nohardlinks)
- [share_limits](Config-Setup#share_limits)

View file

@ -229,6 +229,9 @@ class Config:
"cat_update_all": self.util.check_for_attribute(
self.data, "cat_update_all", parent="settings", var_type="bool", default=True
),
"force_auto_tmm_ignore_tags": self.util.check_for_attribute(
self.data, "force_auto_tmm_ignore_tags", parent="settings", var_type="list", default=[]
),
}
self.tracker_error_tag = self.settings["tracker_error_tag"]

View file

@ -112,7 +112,7 @@ class ShareLimits:
if not self.config.dry_run:
self.qbt.tor_delete_recycle(torrent, attr)
body += logger.print_line(
logger.insert_space("Deleted .torrent but NOT content files.", 8),
logger.insert_space("Deleted .torrent but NOT content files. Reason: is cross-seed", 8),
self.config.loglevel,
)
else:
@ -131,7 +131,13 @@ class ShareLimits:
if not self.config.dry_run:
self.qbt.tor_delete_recycle(torrent, attr)
body += logger.print_line(
logger.insert_space("Deleted .torrent but NOT content files.", 8), self.config.loglevel
logger.insert_space(
"Deleted .torrent but NOT content files. Reason: path does not exist [path="
+ torrent["content_path"].replace(self.root_dir, self.remote_dir)
+ "].",
8,
),
self.config.loglevel,
)
attr["body"] = "\n".join(body)
if not group_notifications:

View file

@ -125,7 +125,9 @@ class Qbt:
logger.separator("Checking Settings", space=False, border=False)
if settings["force_auto_tmm"]:
logger.print_line(
"force_auto_tmm set to True. Will force Auto Torrent Management for all torrents.", self.config.loglevel
"force_auto_tmm set to True. Will force Auto Torrent Management "
"for all torrents without matching force_auto_tmm_ignore_tags.",
self.config.loglevel,
)
logger.separator("Gathering Torrent Information", space=True, border=True)
for torrent in self.torrent_list:
@ -134,7 +136,14 @@ class Qbt:
status = None
working_tracker = None
issue = {"potential": False}
if torrent.auto_tmm is False and settings["force_auto_tmm"] and torrent.category != "" and not self.config.dry_run:
if (
torrent.auto_tmm is False
and settings["force_auto_tmm"]
and torrent.category != ""
and not self.config.dry_run
# check whether the torrent has a matching tag to ignore force_auto_tmm.
and not any(tag in torrent.tags for tag in self.config.settings.get("force_auto_tmm_ignore_tags", []))
):
torrent.set_auto_management(True)
try:
torrent_name = torrent.name

View file

@ -536,22 +536,26 @@ class CheckHardLinks:
def get_inode_count(self):
self.inode_count = {}
for file in self.root_files:
try:
inode_no = os.stat(file.replace(self.root_dir, self.remote_dir)).st_ino
except PermissionError as perm:
logger.warning(f"{perm} : file {file} has permission issues. Skipping...")
# Only check hardlinks for files that are symlinks
if os.path.isfile(file) and os.path.islink(file):
continue
except FileNotFoundError as file_not_found_error:
logger.warning(f"{file_not_found_error} : File {file} not found. Skipping...")
continue
except Exception as ex:
logger.stacktrace()
logger.error(ex)
continue
if inode_no in self.inode_count:
self.inode_count[inode_no] += 1
else:
self.inode_count[inode_no] = 1
try:
inode_no = os.stat(file.replace(self.root_dir, self.remote_dir)).st_ino
except PermissionError as perm:
logger.warning(f"{perm} : file {file} has permission issues. Skipping...")
continue
except FileNotFoundError as file_not_found_error:
logger.warning(f"{file_not_found_error} : File {file} not found. Skipping...")
continue
except Exception as ex:
logger.stacktrace()
logger.error(ex)
continue
if inode_no in self.inode_count:
self.inode_count[inode_no] += 1
else:
self.inode_count[inode_no] = 1
def nohardlink(self, file, notify, ignore_root_dir):
"""

View file

@ -671,8 +671,10 @@ if __name__ == "__main__":
next_run_time = schedule_every_x_minutes(sch)
if startupDelay:
run_mode_message += f"\n Startup Delay: Initial Run will start after {startupDelay} seconds"
logger.info(run_mode_message)
time.sleep(startupDelay)
logger.info(run_mode_message)
else:
logger.info(run_mode_message)
start_loop(True)
while not killer.kill_now:

View file

@ -1,2 +1,2 @@
flake8==7.1.0
pre-commit==3.7.1
flake8==7.1.1
pre-commit==3.8.0

View file

@ -1,7 +1,7 @@
bencodepy==0.9.5
croniter==2.0.5
croniter==3.0.3
GitPython==3.1.43
humanize==4.9.0
humanize==4.10.0
pytimeparse2==1.7.1
qbittorrent-api==2024.8.65
requests==2.32.3

View file

@ -8,7 +8,7 @@ tox_pip_extensions_ext_venv_update = true
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/requirements-dev.txt
passenv = HOME SSH_AUTH_SOCK USER
passenv = HOME,SSH_AUTH_SOCK,USER
[testenv:venv]
envdir = venv