diff --git a/CHANGES.md b/CHANGES.md
index 10c13574..d9ba3777 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,4 +1,24 @@
-### 3.27.13 (2023-04-12 10:15:00 UTC)
+### 3.28.0 (2023-04-12 13:05:00 UTC)
+
+* Update html5lib 1.1 (f87487a) to 1.2-dev (3e500bb)
+* Update package resource API 63.2.0 (3ae44cd) to 67.5.1 (f51eccd)
+* Update Tornado Web Server 6.2.0 (a4f08a3) to 6.3.0 (7186b86)
+* Update urllib3 1.26.13 (25fbd5f) to 1.26.14 (a06c05c)
+* Change remove calls to legacy py2 fix encoding function
+* Change requirements for pure py3
+* Change codebase cleanups
+* Change improve perf by using generators with `any`
+* Change deprecate processEpisode used by nzbToMedia to advise how to configure API instead
+* Change optionally add disk free space in response to three Web API endpoints
+* Change increase API version number to 15
+* Add actually use mount points to get disk free space
+* Add optional "freespace" parameter to endpoints: sg.getrootdirs, sg.addrootdir, sg.deleterootdir
+* Change update help of affected endpoints
+* Fix explicitly save rootdirs after adding or deleting via Web API
+* Change add Rarbg UHD search category
+
+
+### 3.27.13 (2023-04-12 10:15:00 UTC)
* Change fix show id log output
* Change handle exceptions thrown from pkg_resources parsing newly extended working set modules not even used by SG
@@ -771,7 +791,7 @@
* Change allow Python 3.8.10 and 3.9.5
* Remove PiSexy provider
-* Fix refreshShow, prevent another refresh of show if already in queue and not forced
+* Fix refresh_show, prevent another refresh of show if already in queue and not forced
* Fix webapi set scene season
* Fix set path in all_tests for py2
* Fix webapi exception if no backlog was done before (CMD_SickGearCheckScheduler)
@@ -1103,7 +1123,7 @@
* Add API response field `global exclude require` to sg.listrequirewords endpoint
* Change improve Popen resource usage under py2
* Add overall failure monitoring to History/Connect fails (renamed from "Provider fails")
-* Change log exception during updateCache in newznab
+* Change log exception during update_cache in newznab
* Change make Py3.9 preparations
* Change anime "Available groups" to display "No groups listed..." when API is fine with no results instead of blank
* Change improve clarity of anime group lists by using terms Allow list and Block list
diff --git a/_cleaner.py b/_cleaner.py
index bfc31345..60b21232 100644
--- a/_cleaner.py
+++ b/_cleaner.py
@@ -37,6 +37,9 @@ if old_magic != magic_number:
# skip cleaned005 as used during dev by testers
cleanups = [
+ ['.cleaned009.tmp', r'lib\scandir', [
+ r'lib\scandir\__pycache__', r'lib\scandir',
+ ]],
['.cleaned008.tmp', r'lib\tornado_py3', [
r'lib\bs4_py2\builder\__pycache__', r'lib\bs4_py2\builder', r'lib\bs4_py2',
r'lib\bs4_py3\builder\__pycache__', r'lib\bs4_py3\builder', r'lib\bs4_py3',
@@ -122,7 +125,7 @@ for cleaned_path, test_path, dir_list in cleanups:
pass
with io.open(cleaned_file, 'w+', encoding='utf-8') as fp:
- fp.write(u'This file exists to prevent a rerun delete of *.pyc, *.pyo files')
+ fp.write('This file exists to prevent a rerun delete of *.pyc, *.pyo files')
fp.flush()
os.fsync(fp.fileno())
@@ -163,10 +166,10 @@ if not os.path.isfile(cleaned_file) or os.path.exists(test):
swap_name = cleaned_file
cleaned_file = danger_output
danger_output = swap_name
- msg = u'Failed (permissions?) to delete file(s). You must manually delete:\r\n%s' % '\r\n'.join(bad_files)
+ msg = 'Failed (permissions?) to delete file(s). You must manually delete:\r\n%s' % '\r\n'.join(bad_files)
print(msg)
else:
- msg = u'This file exists to prevent a rerun delete of dead lib/html5lib files'
+ msg = 'This file exists to prevent a rerun delete of dead lib/html5lib files'
with io.open(cleaned_file, 'w+', encoding='utf-8') as fp:
fp.write(msg)
diff --git a/gui/slick/interfaces/default/apiBuilder.tmpl b/gui/slick/interfaces/default/apiBuilder.tmpl
index acf1fab1..4b696fb4 100644
--- a/gui/slick/interfaces/default/apiBuilder.tmpl
+++ b/gui/slick/interfaces/default/apiBuilder.tmpl
@@ -70,11 +70,11 @@ addList("Command", "Help", "?cmd=help", "sg.functions-list", "","", "default");
addOption("sg.functions-list", "$k", "&subject=$k", "", "", "#echo ('sb', 'sg')['sg' in $k]#")
#end for
addList("Command", "SickBeard.AddRootDir", "?cmd=sb.addrootdir", "sb.addrootdir");
-addList("Command", "SickGear.AddRootDir", "?cmd=sg.addrootdir", "sb.addrootdir");
+addList("Command", "SickGear.AddRootDir", "?cmd=sg.addrootdir", "sg.addrootdir");
addOption("Command", "SickBeard.CheckScheduler", "?cmd=sb.checkscheduler");
addOption("Command", "SickGear.CheckScheduler", "?cmd=sg.checkscheduler");
addList("Command", "SickBeard.DeleteRootDir", "?cmd=sb.deleterootdir", "sb.deleterootdir");
-addList("Command", "SickGear.DeleteRootDir", "?cmd=sg.deleterootdir", "sb.deleterootdir");
+addList("Command", "SickGear.DeleteRootDir", "?cmd=sg.deleterootdir", "sg.deleterootdir");
addOption("Command", "SickBeard.ForceSearch", "?cmd=sb.forcesearch");
addList("Command", "SickGear.ForceSearch", "?cmd=sg.forcesearch", "sg.forcesearch");
addOption("Command", "SickGear.SearchQueue", "?cmd=sg.searchqueue");
@@ -88,7 +88,7 @@ addList("Command", "SickGear.GetIndexers", "?cmd=sg.getindexers", "listindexers"
addList("Command", "SickGear.GetIndexerIcon", "?cmd=sg.getindexericon", "getindexericon");
addList("Command", "SickGear.GetNetworkIcon", "?cmd=sg.getnetworkicon", "getnetworkicon");
addOption("Command", "SickBeard.GetRootDirs", "?cmd=sb.getrootdirs");
-addOption("Command", "SickGear.GetRootDirs", "?cmd=sg.getrootdirs");
+addList("Command", "SickGear.GetRootDirs", "?cmd=sg.getrootdirs", "sg.addfreespace");
addList("Command", "SickBeard.PauseBacklog", "?cmd=sb.pausebacklog", "sb.pausebacklog");
addList("Command", "SickGear.PauseBacklog", "?cmd=sg.pausebacklog", "sb.pausebacklog");
addOption("Command", "SickBeard.Ping", "?cmd=sb.ping");
@@ -621,10 +621,26 @@ addOption("sb.addrootdir-opt", "Optional Param", "", 1);
addOption("sb.addrootdir-opt", "Default", "&default=1");
addOption("sb.addrootdir-opt", "Not Default", "&default=0");
-addOption("sb.deleterootdir", "C:\\Temp", "&location=C:\\Temp", "", 1);
+addList("sg.addrootdir", "C:\\Temp", "&location=C:\\Temp", "sg.addrootdir-opt");
+addList("sg.addrootdir", "/usr/bin", "&location=/usr/bin/", "sg.addrootdir-opt");
+addList("sg.addrootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location", "sg.addrootdir-opt");
+
+addList("sg.addrootdir-opt", "Optional Param", "", "sg.addfreespace");
+addList("sg.addrootdir-opt", "Default", "&default=1", "sg.addfreespace");
+addList("sg.addrootdir-opt", "Not Default", "&default=0", "sg.addfreespace");
+
+addOption("sb.deleterootdir", "C:\\Temp", "&location=C:\\Temp", 1);
addOption("sb.deleterootdir", "/usr/bin", "&location=/usr/bin/");
addOption("sb.deleterootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location");
+addList("sg.deleterootdir", "C:\\Temp", "&location=C:\\Temp", "sg.addfreespace");
+addList("sg.deleterootdir", "/usr/bin", "&location=/usr/bin/", "sg.addfreespace");
+addList("sg.deleterootdir", "S:\\Invalid_Location", "&location=S:\\Invalid_Location", "sg.addfreespace");
+
+addOption("sg.addfreespace", "Optional Param", "", 1)
+addOption("sg.addfreespace", "incl Freespace", "&freespace=1")
+addOption("sg.addfreespace", "excl Freespace", "&freespace=0")
+
#for $cur_show_obj in $sortedShowList:
addList("show.pause", "$cur_show_obj.name", "&indexerid=$cur_show_obj.prodid", "show.pause-opt");
#end for
diff --git a/gui/slick/interfaces/default/cache.tmpl b/gui/slick/interfaces/default/cache.tmpl
index 7b115f67..be3ba876 100644
--- a/gui/slick/interfaces/default/cache.tmpl
+++ b/gui/slick/interfaces/default/cache.tmpl
@@ -65,7 +65,7 @@
#for $hItem in $cacheResults:
- #set $provider = $providers.getProviderClass($hItem['provider'])
+ #set $provider = $providers.get_by_id($hItem['provider'])
#set $tip = '%s @ %s' % ($hItem['provider'], $SGDatetime.sbfdatetime($SGDatetime.fromtimestamp($hItem['time'])))
#set $ver = $hItem['version']
#set $ver = ($ver, '')[-1 == $ver]
diff --git a/gui/slick/interfaces/default/cast_person.tmpl b/gui/slick/interfaces/default/cast_person.tmpl
index 3ce066a3..3d9b9568 100644
--- a/gui/slick/interfaces/default/cast_person.tmpl
+++ b/gui/slick/interfaces/default/cast_person.tmpl
@@ -182,7 +182,11 @@ def param(visible=True, rid=None, cache_person=None, cache_char=None, person=Non
#end if
#set $section_links = False
+#set $all_sources = $TVInfoAPI().all_sources
#for $cur_src, $cur_sid in sorted(iteritems($person.ids))
+ #if $cur_src not in $all_sources:
+ #continue
+ #end if
#if $TVInfoAPI($cur_src).config.get('people_url')
#if not $section_links
#set $section_links = True
diff --git a/gui/slick/interfaces/default/config.tmpl b/gui/slick/interfaces/default/config.tmpl
index 26b462e9..23d9b4ce 100644
--- a/gui/slick/interfaces/default/config.tmpl
+++ b/gui/slick/interfaces/default/config.tmpl
@@ -29,7 +29,7 @@
$sg_str('CONFIG_FILE') |
- $db.dbFilename() |
+ $db.db_filename() |
#if $db.db_supports_backup
$backup_db_path |
#end if
diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl
index 9f604721..e776220f 100644
--- a/gui/slick/interfaces/default/config_general.tmpl
+++ b/gui/slick/interfaces/default/config_general.tmpl
@@ -13,7 +13,6 @@
#from sickgear.sgdatetime import *
<% def sg_var(varname, default=False): return getattr(sickgear, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickgear, varname, default) %>#slurp#
-#from _23 import list_keys
##
#set global $title = 'Config - General'
#set global $header = 'General Settings'
@@ -846,7 +845,7 @@
File logging level: