Commit c86aadca authored by echel0n's avatar echel0n

Merge branch 'release/v3.2.0'

parents a0b116cd 97d44f9e
......@@ -25,6 +25,7 @@ import signal
import sys
import shutil
import subprocess
import traceback
if sys.version_info < (2, 6):
print "Sorry, requires Python 2.6 or 2.7."
......@@ -68,6 +69,7 @@ throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
signal.signal(signal.SIGINT, sickbeard.sig_handler)
signal.signal(signal.SIGTERM, sickbeard.sig_handler)
class SickRage(object):
def __init__(self):
# system event callback for shutdown/restart
......@@ -127,9 +129,6 @@ class SickRage(object):
try:
locale.setlocale(locale.LC_ALL, "")
except (locale.Error, IOError):
pass
try:
sickbeard.SYS_ENCODING = locale.getpreferredencoding()
except (locale.Error, IOError):
pass
......@@ -146,9 +145,8 @@ class SickRage(object):
# On non-unicode builds this will raise an AttributeError, if encoding type is not valid it throws a LookupError
sys.setdefaultencoding(sickbeard.SYS_ENCODING)
except:
print 'Sorry, you MUST add the SickRage folder to the PYTHONPATH environment variable'
print 'or find another way to force Python to use ' + sickbeard.SYS_ENCODING + ' for string encoding.'
sys.exit(1)
sys.exit("Sorry, you MUST add the SickRage folder to the PYTHONPATH environment variable\n" +
"or find another way to force Python to use " + sickbeard.SYS_ENCODING + " for string encoding.")
# Need console logging for SickBeard.py and SickBeard-console.exe
self.consoleLogging = (not hasattr(sys, "frozen")) or (sickbeard.MY_NAME.lower().find('-console') > 0)
......@@ -456,9 +454,9 @@ class SickRage(object):
sickbeard.showList.append(curShow)
except Exception, e:
logger.log(
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8',
'replace'),
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
logger.ERROR)
logger.log(traceback.format_exc(), logger.DEBUG)
def restore(self, srcDir, dstDir):
try:
......@@ -508,7 +506,7 @@ class SickRage(object):
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID),
sys.executable]
else:
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
logger.log(u"Unknown SR launch method, please file a bug report about this", logger.ERROR)
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'),
str(sickbeard.PID),
sys.executable,
......
......@@ -38,7 +38,9 @@ addOption("Command", "SickBeard.GetRootDirs", "?cmd=sb.getrootdirs", "", "", "ac
addList("Command", "SickBeard.PauseBacklog", "?cmd=sb.pausebacklog", "sb.pausebacklog", "", "", "action");
addOption("Command", "SickBeard.Ping", "?cmd=sb.ping", "", "", "action");
addOption("Command", "SickBeard.Restart", "?cmd=sb.restart", "", "", "action");
addList("Command", "SickBeard.SearchTVDB", "?cmd=sb.searchtvdb", "sb.searchtvdb", "", "", "action");
addList("Command", "SickBeard.SearchAllIndexers", "?cmd=sb.searchindexers", "sb.searchindexers", "", "", "action");
addList("Command", "SickBeard.SearchTVDB", "?cmd=sb.searchtvdb&indexer=1", "sb.searchindexers", "", "", "action");
addList("Command", "SickBeard.SearchTVRage", "?cmd=sb.searchtvrage&indexer=2", "sb.searchindexers", "", "", "action");
addList("Command", "SickBeard.SetDefaults", "?cmd=sb.setdefaults", "sb.setdefaults", "", "", "action");
addOption("Command", "SickBeard.Shutdown", "?cmd=sb.shutdown", "", "", "action");
addList("Command", "Coming Episodes", "?cmd=future", "future");
......@@ -140,44 +142,44 @@ addOption("show.addnew-opt", "Optional Param", "", 1);
addList("show.addnew-opt", "No Season Folder", "&season_folder=0", "quality");
addList("show.addnew-opt", "Use Season Folder", "&season_folder=1", "quality");
addOptGroup("sb.searchtvdb", "Search by Name");
addList("sb.searchtvdb", "Lost", "&name=Lost", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "office", "&name=office", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "OffiCE", "&name=OffiCE", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "Leno", "&name=leno", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "Top Gear", "&name=Top Gear", "sb.searchtvdb-lang");
endOptGroup("sb.searchtvdb");
addOptGroup("sb.searchtvdb", "Search by indexerid");
addList("sb.searchtvdb", "73739", "&indexerid=73739", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "74608", "&indexerid=74608", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "199051", "&indexerid=199051", "sb.searchtvdb-lang");
addList("sb.searchtvdb", "123456 (invalid show)", "&indexerid=123456", "sb.searchtvdb-lang");
endOptGroup("sb.searchtvdb");
addOption("sb.searchtvdb-lang", "Optional Param", "", 1);
addOption("sb.searchtvdb-lang", "Chinese", "&lang=zh"); // 27
addOption("sb.searchtvdb-lang", "Croatian", "&lang=hr"); // 31
addOption("sb.searchtvdb-lang", "Czech", "&lang=cs"); // 28
addOption("sb.searchtvdb-lang", "Danish", "&lang=da"); // 10
addOption("sb.searchtvdb-lang", "Dutch", "&lang=nl"); // 13
addOption("sb.searchtvdb-lang", "English", "&lang=en"); // 7
addOption("sb.searchtvdb-lang", "Finnish", "&lang=fi"); // 11 -- Suomeksi
addOption("sb.searchtvdb-lang", "French", "&lang=fr"); // 17
addOption("sb.searchtvdb-lang", "German", "&lang=de"); // 14
addOption("sb.searchtvdb-lang", "Greek", "&lang=el"); // 20
addOption("sb.searchtvdb-lang", "Hebrew", "&lang=he"); // 24
addOption("sb.searchtvdb-lang", "Hungarian", "&lang=hu"); // 19 -- Magyar
addOption("sb.searchtvdb-lang", "Italian", "&lang=it"); // 15
addOption("sb.searchtvdb-lang", "Japanese", "&lang=ja"); // 25
addOption("sb.searchtvdb-lang", "Korean", "&lang=ko"); // 32
addOption("sb.searchtvdb-lang", "Norwegian", "&lang=no"); // 9
addOption("sb.searchtvdb-lang", "Polish", "&lang=pl"); // 18
addOption("sb.searchtvdb-lang", "Portuguese", "&lang=pt");// 26
addOption("sb.searchtvdb-lang", "Russian", "&lang=ru"); // 22
addOption("sb.searchtvdb-lang", "Slovenian", "&lang=sl"); // 30
addOption("sb.searchtvdb-lang", "Spanish", "&lang=es"); // 16
addOption("sb.searchtvdb-lang", "Swedish", "&lang=sv"); // 8
addOption("sb.searchtvdb-lang", "Turkish", "&lang=tr"); // 21
addOptGroup("sb.searchindexers", "Search by Name");
addList("sb.searchindexers", "Lost", "&name=Lost", "sb.searchindexers-lang");
addList("sb.searchindexers", "office", "&name=office", "sb.searchindexers-lang");
addList("sb.searchindexers", "OffiCE", "&name=OffiCE", "sb.searchindexers-lang");
addList("sb.searchindexers", "Leno", "&name=leno", "sb.searchindexers-lang");
addList("sb.searchindexers", "Top Gear", "&name=Top Gear", "sb.searchindexers-lang");
endOptGroup("sb.searchindexers");
addOptGroup("sb.searchindexers", "Search by indexerid");
addList("sb.searchindexers", "73739", "&indexerid=73739", "sb.searchindexers-lang");
addList("sb.searchindexers", "74608", "&indexerid=74608", "sb.searchindexers-lang");
addList("sb.searchindexers", "199051", "&indexerid=199051", "sb.searchindexers-lang");
addList("sb.searchindexers", "123456 (invalid show)", "&indexerid=123456", "sb.searchindexers-lang");
endOptGroup("sb.searchindexers");
addOption("sb.searchindexers-lang", "Optional Param", "", 1);
addOption("sb.searchindexers-lang", "Chinese", "&lang=zh"); // 27
addOption("sb.searchindexers-lang", "Croatian", "&lang=hr"); // 31
addOption("sb.searchindexers-lang", "Czech", "&lang=cs"); // 28
addOption("sb.searchindexers-lang", "Danish", "&lang=da"); // 10
addOption("sb.searchindexers-lang", "Dutch", "&lang=nl"); // 13
addOption("sb.searchindexers-lang", "English", "&lang=en"); // 7
addOption("sb.searchindexers-lang", "Finnish", "&lang=fi"); // 11 -- Suomeksi
addOption("sb.searchindexers-lang", "French", "&lang=fr"); // 17
addOption("sb.searchindexers-lang", "German", "&lang=de"); // 14
addOption("sb.searchindexers-lang", "Greek", "&lang=el"); // 20
addOption("sb.searchindexers-lang", "Hebrew", "&lang=he"); // 24
addOption("sb.searchindexers-lang", "Hungarian", "&lang=hu"); // 19 -- Magyar
addOption("sb.searchindexers-lang", "Italian", "&lang=it"); // 15
addOption("sb.searchindexers-lang", "Japanese", "&lang=ja"); // 25
addOption("sb.searchindexers-lang", "Korean", "&lang=ko"); // 32
addOption("sb.searchindexers-lang", "Norwegian", "&lang=no"); // 9
addOption("sb.searchindexers-lang", "Polish", "&lang=pl"); // 18
addOption("sb.searchindexers-lang", "Portuguese", "&lang=pt");// 26
addOption("sb.searchindexers-lang", "Russian", "&lang=ru"); // 22
addOption("sb.searchindexers-lang", "Slovenian", "&lang=sl"); // 30
addOption("sb.searchindexers-lang", "Spanish", "&lang=es"); // 16
addOption("sb.searchindexers-lang", "Swedish", "&lang=sv"); // 8
addOption("sb.searchindexers-lang", "Turkish", "&lang=tr"); // 21
#for $curShow in $sortedShowList:
addList("seasons", "$curShow.name", "&indexerid=$curShow.indexerid", "seasons-$curShow.indexerid");
......
......@@ -198,19 +198,6 @@
<div id="summary">
<table class="summaryTable pull-left">
#if $show.network and $show.airs:
<tr><td class="showLegend">Originally Airs: </td><td>$show.airs #if not $network_timezones.test_timeformat($show.airs) then " <font color='#FF0000'><b>(invalid Timeformat)</b></font> " else ""# on $show.network</td></tr>
#else if $show.network:
<tr><td class="showLegend">Originally Airs: </td><td>$show.network</td></tr>
#else if $show.airs:
<tr><td class="showLegend">Originally Airs: </td><td>>$show.airs #if not $network_timezones.test_timeformat($show.airs) then " <font color='#FF0000'><b>(invalid Timeformat)</b></font> " else ""#</td></tr>
#end if
<tr><td class="showLegend">Status: </td><td>$show.status</td></tr>
#if $showLoc[1]:
<tr><td class="showLegend">Location: </td><td>$showLoc[0]</td></tr>
#else:
<tr><td class="showLegend"><span style="color: red;">Location: </span></td><td><span style="color: red;">$showLoc[0]</span> (dir is missing)</td></tr>
#end if
#set $anyQualities, $bestQualities = $Quality.splitQuality(int($show.quality))
<tr><td class="showLegend">Quality: </td><td>
#if $show.quality in $qualityPresets:
......@@ -222,6 +209,21 @@
#if $bestQualities:
<i>Replace with:</i> <%=", ".join([Quality.qualityStrings[x] for x in sorted(bestQualities)])%>
#end if
#end if
#if $show.network and $show.airs:
<tr><td class="showLegend">Originally Airs: </td><td>$show.airs #if not $network_timezones.test_timeformat($show.airs) then " <font color='#FF0000'><b>(invalid Timeformat)</b></font> " else ""# on $show.network</td></tr>
#else if $show.network:
<tr><td class="showLegend">Originally Airs: </td><td>$show.network</td></tr>
#else if $show.airs:
<tr><td class="showLegend">Originally Airs: </td><td>>$show.airs #if not $network_timezones.test_timeformat($show.airs) then " <font color='#FF0000'><b>(invalid Timeformat)</b></font> " else ""#</td></tr>
#end if
<tr><td class="showLegend">Show Status: </td><td>$show.status</td></tr>
<tr><td class="showLegend">Default EP Status: </td><td>$statusStrings[$show.default_ep_status]</td></tr>
#if $showLoc[1]:
<tr><td class="showLegend">Location: </td><td>$showLoc[0]</td></tr>
#else:
<tr><td class="showLegend"><span style="color: red;">Location: </span></td><td><span style="color: red;">$showLoc[0]</span> (dir is missing)</td></tr>
#end if
<tr><td class="showLegend">Scene Name:</td><td>#if $show.exceptions then $exceptions_string else $show.name#</td></tr>
......@@ -263,14 +265,13 @@
#end if
</table>
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="pull-left" style="padding-bottom: 10px;">
Change selected episodes to
<div class="pull-left" >
Change selected episodes to:</br>
<select id="statusSelect" class="form-control form-control-inline input-sm">
#for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED, $FAILED] + sorted($Quality.DOWNLOADED):
#if $curStatus == $DOWNLOADED:
......@@ -284,6 +285,8 @@
<input class="btn btn-inline" type="button" id="changeStatus" value="Go" />
</div>
</br>
<div class="pull-right clearfix" id="checkboxControls">
<div style="padding-bottom: 5px;">
<label for="wanted"><span class="wanted"><input type="checkbox" id="wanted" checked="checked" /> Wanted: <b>$epCounts[$Overview.WANTED]</b></span></label>
......@@ -298,7 +301,6 @@
<button class="btn btn-xs clearAll">Clear All</button>
</div>
</div>
<br />
<table class="sickbeardTable display_show" cellspacing="0" border="0" cellpadding="0">
......
#import sickbeard
#import lib.adba as adba
#from sickbeard import common
#from sickbeard.common import *
#from sickbeard import exceptions
#from sickbeard import scene_exceptions
#from sickbeard.blackandwhitelist import *
......@@ -63,35 +64,21 @@
<form action="editShow" method="post">
<input type="hidden" name="show" value="$show.indexerid" />
<b>Location:</b> <input type="text" name="location" id="location" value="$show._location" class="form-control form-control-inline input-sm input350" /><br />
<br />
<b>Quality:</b>
#set $qualities = $common.Quality.splitQuality(int($show.quality))
#set global $anyQualities = $qualities[0]
#set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl")
<b>Location:</b></br>
<input type="text" name="location" id="location" value="$show._location" class="form-control form-control-inline input-sm input350" /><br />
<br />
#if $anyQualities + $bestQualities
<b>Archive on first match: </b>
<input type="checkbox" name="archive_firstmatch" #if $show.archive_firstmatch == 1 then "checked=\"checked\"" else ""# /><br>
(check this to have the episode archived after the first best match is found from your archive quality list)
<br />
<br />
#end if
<b>Scene Exception:</b>
<input type="text" id="SceneName" class="form-control form-control-inline input-sm input200">
<b>Scene Exception:</b><br />
<input type="text" id="SceneName" class="form-control form-control-inline input-sm input200">
<input class="btn btn-inline" type="button" value="Add" id="addSceneName"><br />
<div id="SceneException" >
<div>
<p>This will <b>affect the episode show search</b> on nzb and torrent provider.<br />
This list overrides the original name, it doesn't append to it.<br />
</p>
</div>
</div>
<div class="pull-left" style="text-align:center;">
<h4>Exceptions List</h4>
<select id="exceptions_list" name="exceptions_list" multiple="multiple" style="min-width:10em;" >
......@@ -99,54 +86,84 @@
<option value="$cur_exception">$cur_exception</option>
#end for
</select>
<div>
<div>
<input id="removeSceneName" value="Remove" class="btn float-left" type="button" style="margin-top: 10px;"/>
</div>
</div>
<br />
</div>
</div>
</div>
<div class="clearfix"></div>
<br />
<b>Info Language:</b> <select name="indexerLang" id="indexerLangSelect" class="form-control form-control-inline input-sm"></select><br />
Note: This will only affect the language of the retrieved metadata file contents and episode filenames.<br />
This <b>DOES NOT</b> allow SickRage to download non-english TV episodes!<br />
<b>Quality:</b><br />
#set $qualities = $common.Quality.splitQuality(int($show.quality))
#set global $anyQualities = $qualities[0]
#set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl")
<br />
<b>Default Episode Status:</b><br />
(this will set a default status to be applied to any newly added episodes)<br />
<select name="defaultEpStatus" id="defaultEpStatusSelect" class="form-control form-control-inline input-sm">
#for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED]:
<option value="$curStatus">$statusStrings[$curStatus]</option>
#end for
</select><br />
<br />
<b>Flatten files (no folders):</b> <input type="checkbox" name="flatten_folders" #if $show.flatten_folders == 1 and not $sickbeard.NAMING_FORCE_FOLDERS then "checked=\"checked\"" else ""# #if $sickbeard.NAMING_FORCE_FOLDERS then "disabled=\"disabled\"" else ""#/><br /><br />
<b>Paused:</b> <input type="checkbox" name="paused" #if $show.paused == 1 then "checked=\"checked\"" else ""# /><br /><br />
<b>Subtitles:</b> <input type="checkbox" name="subtitles"#if $show.subtitles == 1 and $sickbeard.USE_SUBTITLES then " checked=\"checked\"" else ""##if not $sickbeard.USE_SUBTITLES then " disabled=\"disabled\"" else ""#/><br /><br />
<b>Info Language:</b><br />
(this will only affect the language of the retrieved metadata file contents and episode filenames)<br />
<select name="indexerLang" id="indexerLangSelect" class="form-control form-control-inline input-sm"></select><br />
<br />
<b>Flatten files (no folders):</b> <input type="checkbox" name="flatten_folders" #if $show.flatten_folders == 1 and not $sickbeard.NAMING_FORCE_FOLDERS then "checked=\"checked\"" else ""# #if $sickbeard.NAMING_FORCE_FOLDERS then "disabled=\"disabled\"" else ""#/><br />
<b>Paused:</b> <input type="checkbox" name="paused" #if $show.paused == 1 then "checked=\"checked\"" else ""# /><br />
<b>Subtitles:</b> <input type="checkbox" name="subtitles"#if $show.subtitles == 1 and $sickbeard.USE_SUBTITLES then " checked=\"checked\"" else ""##if not $sickbeard.USE_SUBTITLES then " disabled=\"disabled\"" else ""#/><br />
<br/>
<b>Scene Numbering: </b>
<input type="checkbox" name="scene" #if $show.scene == 1 then "checked=\"checked\"" else ""# /><br/>
(check this if you wish to search by scene numbering, uncheck to search by indexer numbering)
<br/><br/>
<b>Air by date: </b>
(check this if you wish to search by scene numbering, uncheck to search by indexer numbering)<br/>
<br/>
<b>Air by date: </b>
<input type="checkbox" name="air_by_date" #if $show.air_by_date == 1 then "checked=\"checked\"" else ""# /><br />
(check this if the show is released as Show.03.02.2010 rather than Show.S02E03)
<br /><br />
(check this if the show is released as Show.03.02.2010 rather than Show.S02E03)<br />
<br />
<b>Sports: </b>
<input type="checkbox" name="sports" #if $show.sports == 1 then "checked=\"checked\"" else ""# /><br />
(check this if the show is a sporting or MMA event)
<br /><br />
(check this if the show is a sporting or MMA event)<br />
<br />
<b>Anime: </b>
<input type="checkbox" name="anime" #if $show.is_anime then "CHECKED" else ""#><br />
(check this if the show is released as Show.265 rather than Show.S02E03, this show is an anime)
<br /><br />
(check this if the show is released as Show.265 rather than Show.S02E03, this show is an anime)<br />
<br />
<b>DVD Order: </b>
<input type="checkbox" name="dvdorder" #if $show.dvdorder == 1 then "checked=\"checked\"" else ""# /><br/>
(check this if you wish to use the DVD order instead of the Airing order)
<br/><br/>
<b>Ignored Words:</b> <input type="text" name="rls_ignore_words" id="rls_ignore_words" value="$show.rls_ignore_words" class="form-control form-control-inline input-sm input350" /><br />
Results with any of these words in the title will be filtered out <br />
Separate words with a comma, e.g. "word1,word2,word3"
<br /><br />
#if $anyQualities + $bestQualities
<b>Archive on first match:</b>
<input type="checkbox" name="archive_firstmatch" #if $show.archive_firstmatch == 1 then "checked=\"checked\"" else ""# /><br>
(check this to have the episode archived after the first best match is found from your archive quality list)</br>
<br />
#end if
<b>Ignored Words:</b></br>
<input type="text" name="rls_ignore_words" id="rls_ignore_words" value="$show.rls_ignore_words" class="form-control form-control-inline input-sm input350" /><br />
Results with any of these words in the title will be filtered out<br />
Separate words with a comma, e.g. "word1,word2,word3"<br />
<br />
<b>Required Words:</b> <input type="text" name="rls_require_words" id="rls_require_words" value="$show.rls_require_words" class="form-control form-control-inline input-sm input350" /><br />
<b>Required Words:</b></br>
<input type="text" name="rls_require_words" id="rls_require_words" value="$show.rls_require_words" class="form-control form-control-inline input-sm input350" /><br />
Results without one of these words in the title will be filtered out <br />
Separate words with a comma, e.g. "word1,word2,word3"
<br /><br />
Separate words with a comma, e.g. "word1,word2,word3"<br />
<br />
#if $show.is_anime:
#from sickbeard.blackandwhitelist import *
......
......@@ -280,10 +280,13 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#set $cur_downloaded = 0
#set $cur_total = 0
#set $download_stat_tip = ''
#if None is not $curShow.status and re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
#set $display_status = 'Continuing'
#else
#set $display_status = $curShow.status
#set $display_status = $curShow.status
#if None is not $display_status
#if re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
#set $display_status = 'Continuing'
#else if re.search(r'(?i)(?:nded)', $curShow.status)
#set $display_status = 'Ended'
#end if
#end if
#if $curShow.indexerid in $show_stat:
......@@ -604,11 +607,17 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
</td>
<td align="center">
#if None is not $curShow.status and re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
Continuing
#else:
$curShow.status
#set $display_status = $curShow.status
#if None is not $display_status
#if re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
#set $display_status = 'Continuing'
#else if re.search(r'(?i)(?:nded)', $curShow.status)
#set $display_status = 'Ended'
#end if
#end if
$display_status
</td>
</tr>
......
......@@ -43,16 +43,6 @@
<link rel="stylesheet" type="text/css" href="$sbRoot/css/${sickbeard.THEME_NAME}.css?$sbPID" />
<style type="text/css">
<!--
#if $sickbeard.NEWEST_VERSION_STRING:
.ui-pnotify { top: 30px !important; }
#end if
//-->
</style>
<script type="text/javascript" src="$sbRoot/js/lib/jquery-1.8.3.min.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/lib/bootstrap.min.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/lib/bootstrap-hover-dropdown.min.js?$sbPID"></script>
......
# -*- coding: utf-8 -*-
"""
ftfy: fixes text for you
This is a module for making text less broken. See the `fix_text` function
for more information.
"""
from __future__ import unicode_literals
# See the docstring for ftfy.bad_codecs to see what we're doing here.
import ftfy.bad_codecs
ftfy.bad_codecs.ok()
from ftfy import fixes
from ftfy.fixes import fix_text_encoding
from ftfy.compatibility import PYTHON34_OR_LATER, is_printable
import unicodedata
import warnings
def fix_text(text,
remove_unsafe_private_use=(not PYTHON34_OR_LATER),
fix_entities='auto',
remove_terminal_escapes=True,
fix_encoding=True,
normalization='NFKC',
uncurl_quotes=True,
fix_line_breaks=True,
remove_control_chars=True,
remove_bom=True,
max_decode_length=2**16):
r"""
Given Unicode text as input, make its representation consistent and
possibly less broken.
Let's start with some examples:
>>> print(fix_text('ünicode'))
ünicode
>>> print(fix_text('Broken text&hellip; it&#x2019;s flubberific!'))
Broken text... it's flubberific!
>>> print(fix_text('HTML entities &lt;3'))
HTML entities <3
>>> print(fix_text('<em>HTML entities &lt;3</em>'))
<em>HTML entities &lt;3</em>
>>> print(fix_text('\001\033[36;44mI&#x92;m blue, da ba dee da ba '
... 'doo&#133;\033[0m'))
I'm blue, da ba dee da ba doo...
>>> # This example string starts with a byte-order mark, even if
>>> # you can't see it on the Web.
>>> print(fix_text('\ufeffParty like\nit&rsquo;s 1999!'))
Party like
it's 1999!
>>> len(fix_text('fi' * 100000))
200000
>>> len(fix_text(''))
0
Based on the options you provide, ftfy applies these steps in order:
- If `remove_unsafe_private_use` is True, it removes a range of private-use
characters that could trigger a Python bug. The bug is fixed in
the most recent versions of Python, so this will default to False
starting on Python 3.4.
- If `fix_entities` is True, replace HTML entities with their equivalent
characters. If it's "auto" (the default), then consider replacing HTML
entities, but don't do so in text where you have seen a pair of actual
angle brackets (that's probably actually HTML and you shouldn't mess
with the entities).
- If `remove_terminal_escapes` is True, remove sequences of bytes that are
instructions for Unix terminals, such as the codes that make text appear
in different colors.
- If `fix_encoding` is True, look for common mistakes that come from
encoding or decoding Unicode text incorrectly, and fix them if they are
reasonably fixable. See `fix_text_encoding` for details.
- If `normalization` is not None, apply the specified form of Unicode
normalization, which can be one of 'NFC', 'NFKC', 'NFD', and 'NFKD'.
The default, 'NFKC', applies the following relevant transformations:
- C: Combine characters and diacritics that are written using separate
code points, such as converting "e" plus an acute accent modifier
into "é", or converting "ka" (か) plus a dakuten into the
single character "ga" (が).
- K: Replace characters that are functionally equivalent with the most
common form. For example, half-width katakana will be replaced with
full-width versions, full-width Roman characters will be replaced with
ASCII characters, ellipsis characters will be replaced with three
periods, and the ligature 'fl' will be replaced with 'fl'.
- If `uncurl_quotes` is True, replace various curly quotation marks with
plain-ASCII straight quotes.
- If `fix_line_breaks` is true, convert all line breaks to Unix style
(CRLF and CR line breaks become LF line breaks).
- If `fix_control_characters` is true, remove all C0 control characters
except the common useful ones: TAB, CR, LF, and FF. (CR characters
may have already been removed by the `fix_line_breaks` step.)
- If `remove_bom` is True, remove the Byte-Order Mark if it exists.
- If anything was changed, repeat all the steps, so that the function is
idempotent. "&amp;amp;" will become "&", for example, not "&amp;".
`fix_text` will work one line at a time, with the possibility that some
lines are in different encodings. When it encounters lines longer than
`max_decode_length`, it will not run the `fix_encoding` step, to avoid
unbounded slowdowns.
If you are certain your entire text is in the same encoding (though that
encoding is possibly flawed), and do not mind performing operations on
the whole text at once, use `fix_text_segment`.
"""
if isinstance(text, bytes):
raise UnicodeError(fixes.BYTES_ERROR_TEXT)
out = []
pos = 0
while pos < len(text):
textbreak = text.find('\n', pos) + 1
fix_encoding_this_time = fix_encoding
if textbreak == 0:
textbreak = len(text)
if (textbreak - pos) > max_decode_length:
fix_encoding_this_time = False
substring = text[pos:textbreak]
if fix_entities == 'auto' and '<' in substring and '>' in substring:
# we see angle brackets together; this could be HTML
fix_entities = False
out.append(
fix_text_segment(
substring,
remove_unsafe_private_use=remove_unsafe_private_use,
fix_entities=fix_entities,
remove_terminal_escapes=remove_terminal_escapes,
fix_encoding=fix_encoding_this_time,
normalization=normalization,
uncurl_quotes=uncurl_quotes,
fix_line_breaks=fix_line_breaks,
remove_control_chars=remove_control_chars,
remove_bom=remove_bom
)