Skip to content

Commit

Permalink
Merge pull request #11162 from pymedusa/release/release-1.0.12
Browse files Browse the repository at this point in the history
Release/release 1.0.12
  • Loading branch information
medariox committed Mar 7, 2023
2 parents b9292f9 + 7d78dbb commit 671a443
Show file tree
Hide file tree
Showing 233 changed files with 12,651 additions and 8,419 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 1.0.12 (03-03-2023)

#### New Features
- Add RSS Feed Client (Thanks to @sawyersteven)

#### Improvements
- Update many Python dependencies

#### Fixes
- Ensure that git_path is a valid file (Thanks to @pizza-power)
- Avoid exception when the filepart doesn't match a season
- Encode NZBGet username, password and host

-----

## 1.0.11 (14-01-2023)

#### Improvements
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ RUN \
mkdir /tmp/unrar-install && \
tar xf /tmp/unrar-pkg/unrar-*.apk -C /tmp/unrar-install

FROM python:3.10.4-alpine3.15
FROM python:3.10.8-alpine3.15
LABEL maintainer="pymedusa"

ARG GIT_BRANCH
Expand Down
1 change: 0 additions & 1 deletion ext/_version.py

This file was deleted.

File renamed without changes.
136 changes: 79 additions & 57 deletions ext3/bs4/__init__.py → ext/bs4/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
provides methods and Pythonic idioms that make it easy to navigate,
search, and modify the parse tree.
Beautiful Soup works with Python 2.7 and up. It works better if lxml
Beautiful Soup works with Python 3.6 and up. It works better if lxml
and/or html5lib is installed.
For more than you ever wanted to know about Beautiful Soup, see the
documentation: http://www.crummy.com/software/BeautifulSoup/bs4/doc/
"""

__author__ = "Leonard Richardson (leonardr@segfault.org)"
__version__ = "4.9.3"
__copyright__ = "Copyright (c) 2004-2020 Leonard Richardson"
__version__ = "4.11.2"
__copyright__ = "Copyright (c) 2004-2023 Leonard Richardson"
# Use of this source code is governed by the MIT license.
__license__ = "MIT"

Expand All @@ -29,7 +29,16 @@
import traceback
import warnings

from .builder import builder_registry, ParserRejectedMarkup
# The very first thing we do is give a useful error if someone is
# running this code under Python 2.
if sys.version_info.major < 3:
raise ImportError('You are trying to use a Python 3-specific version of Beautiful Soup under Python 2. This will not work. The final version of Beautiful Soup to support Python 2 was 4.9.3.')

from .builder import (
builder_registry,
ParserRejectedMarkup,
XMLParsedAsHTMLWarning,
)
from .dammit import UnicodeDammit
from .element import (
CData,
Expand All @@ -49,10 +58,6 @@
TemplateString,
)

# The very first thing we do is give a useful error if someone is
# running this code under Python 3 without converting it.
'You are trying to run the Python 2 version of Beautiful Soup under Python 3. This will not work.'!='You need to convert the code, either by installing it (`python setup.py install`) or by running 2to3 (`2to3 -w bs4`).'

# Define some custom warnings.
class GuessedAtParserWarning(UserWarning):
"""The warning issued when BeautifulSoup has to guess what parser to
Expand All @@ -65,7 +70,7 @@ class MarkupResemblesLocatorWarning(UserWarning):
on disk.
"""


class BeautifulSoup(Tag):
"""A data structure representing a parsed HTML or XML document.
Expand Down Expand Up @@ -205,10 +210,10 @@ def deprecated_argument(old_name, new_name):
if old_name in kwargs:
warnings.warn(
'The "%s" argument to the BeautifulSoup constructor '
'has been renamed to "%s."' % (old_name, new_name))
value = kwargs[old_name]
del kwargs[old_name]
return value
'has been renamed to "%s."' % (old_name, new_name),
DeprecationWarning, stacklevel=3
)
return kwargs.pop(old_name)
return None

parse_only = parse_only or deprecated_argument(
Expand Down Expand Up @@ -303,39 +308,18 @@ def deprecated_argument(old_name, new_name):
self._namespaces = dict()
self.parse_only = parse_only

self.builder.initialize_soup(self)

if hasattr(markup, 'read'): # It's a file-type object.
markup = markup.read()
elif len(markup) <= 256 and (
(isinstance(markup, bytes) and not b'<' in markup)
or (isinstance(markup, str) and not '<' in markup)
):
# Print out warnings for a couple beginner problems
# Issue warnings for a couple beginner problems
# involving passing non-markup to Beautiful Soup.
# Beautiful Soup will still parse the input as markup,
# just in case that's what the user really wants.
if (isinstance(markup, str)
and not os.path.supports_unicode_filenames):
possible_filename = markup.encode("utf8")
else:
possible_filename = markup
is_file = False
try:
is_file = os.path.exists(possible_filename)
except Exception as e:
# This is almost certainly a problem involving
# characters not valid in filenames on this
# system. Just let it go.
pass
if is_file:
warnings.warn(
'"%s" looks like a filename, not markup. You should'
' probably open this file and pass the filehandle into'
' Beautiful Soup.' % self._decode_markup(markup),
MarkupResemblesLocatorWarning
)
self._check_markup_is_url(markup)
# since that is sometimes the intended behavior.
if not self._markup_is_url(markup):
self._markup_resembles_filename(markup)

rejections = []
success = False
Expand All @@ -344,6 +328,7 @@ def deprecated_argument(old_name, new_name):
self.builder.prepare_markup(
markup, from_encoding, exclude_encodings=exclude_encodings)):
self.reset()
self.builder.initialize_soup(self)
try:
self._feed()
success = True
Expand Down Expand Up @@ -379,10 +364,10 @@ def __copy__(self):
def __getstate__(self):
# Frequently a tree builder can't be pickled.
d = dict(self.__dict__)
if 'builder' in d and not self.builder.picklable:
if 'builder' in d and d['builder'] is not None and not self.builder.picklable:
d['builder'] = None
return d

@classmethod
def _decode_markup(cls, markup):
"""Ensure `markup` is bytes so it's safe to send into warnings.warn.
Expand All @@ -397,11 +382,13 @@ def _decode_markup(cls, markup):
return decoded

@classmethod
def _check_markup_is_url(cls, markup):
def _markup_is_url(cls, markup):
"""Error-handling method to raise a warning if incoming markup looks
like a URL.
:param markup: A string.
:return: Whether or not the markup resembles a URL
closely enough to justify a warning.
"""
if isinstance(markup, bytes):
space = b' '
Expand All @@ -410,20 +397,51 @@ def _check_markup_is_url(cls, markup):
space = ' '
cant_start_with = ("http:", "https:")
else:
return
return False

if any(markup.startswith(prefix) for prefix in cant_start_with):
if not space in markup:
warnings.warn(
'"%s" looks like a URL. Beautiful Soup is not an'
' HTTP client. You should probably use an HTTP client like'
' requests to get the document behind the URL, and feed'
' that document to Beautiful Soup.' % cls._decode_markup(
markup
),
MarkupResemblesLocatorWarning
'The input looks more like a URL than markup. You may want to use'
' an HTTP client like requests to get the document behind'
' the URL, and feed that document to Beautiful Soup.',
MarkupResemblesLocatorWarning,
stacklevel=3
)
return True
return False

@classmethod
def _markup_resembles_filename(cls, markup):
"""Error-handling method to raise a warning if incoming markup
resembles a filename.
:param markup: A bytestring or string.
:return: Whether or not the markup resembles a filename
closely enough to justify a warning.
"""
path_characters = '/\\'
extensions = ['.html', '.htm', '.xml', '.xhtml', '.txt']
if isinstance(markup, bytes):
path_characters = path_characters.encode("utf8")
extensions = [x.encode('utf8') for x in extensions]
filelike = False
if any(x in markup for x in path_characters):
filelike = True
else:
lower = markup.lower()
if any(lower.endswith(ext) for ext in extensions):
filelike = True
if filelike:
warnings.warn(
'The input looks more like a filename than markup. You may'
' want to open this file and pass the filehandle into'
' Beautiful Soup.',
MarkupResemblesLocatorWarning, stacklevel=3
)
return True
return False

def _feed(self):
"""Internal method that parses previously set markup, creating a large
number of Tag and NavigableString objects.
Expand Down Expand Up @@ -485,7 +503,7 @@ def string_container(self, base_class=None):

# On top of that, we may be inside a tag that needs a special
# container class.
if self.string_container_stack:
if self.string_container_stack and container is NavigableString:
container = self.builder.string_containers.get(
self.string_container_stack[-1].name, container
)
Expand Down Expand Up @@ -541,9 +559,7 @@ def pushTag(self, tag):
def endData(self, containerClass=None):
"""Method called by the TreeBuilder when the end of a data segment
occurs.
"""
containerClass = self.string_container(containerClass)

"""
if self.current_data:
current_data = ''.join(self.current_data)
# If whitespace is not preserved, and this string contains
Expand All @@ -570,6 +586,7 @@ def endData(self, containerClass=None):
not self.parse_only.search(current_data)):
return

containerClass = self.string_container(containerClass)
o = containerClass(current_data)
self.object_was_parsed(o)

Expand Down Expand Up @@ -676,7 +693,7 @@ def _popToTag(self, name, nsprefix=None, inclusivePop=True):
return most_recently_popped

def handle_starttag(self, name, namespace, nsprefix, attrs, sourceline=None,
sourcepos=None):
sourcepos=None, namespaces=None):
"""Called by the tree builder when a new tag is encountered.
:param name: Name of the tag.
Expand All @@ -686,6 +703,8 @@ def handle_starttag(self, name, namespace, nsprefix, attrs, sourceline=None,
source document.
:param sourcepos: The character position within `sourceline` where this
tag was found.
:param namespaces: A dictionary of all namespace prefix mappings
currently in scope in the document.
If this method returns None, the tag was rejected by an active
SoupStrainer. You should proceed as if the tag had not occurred
Expand All @@ -703,7 +722,8 @@ def handle_starttag(self, name, namespace, nsprefix, attrs, sourceline=None,
tag = self.element_classes.get(Tag, Tag)(
self, self.builder, name, namespace, nsprefix, attrs,
self.currentTag, self._most_recent_element,
sourceline=sourceline, sourcepos=sourcepos
sourceline=sourceline, sourcepos=sourcepos,
namespaces=namespaces
)
if tag is None:
return tag
Expand All @@ -722,7 +742,7 @@ def handle_endtag(self, name, nsprefix=None):
#print("End tag: " + name)
self.endData()
self._popToTag(name, nsprefix)

def handle_data(self, data):
"""Called by the tree builder when a chunk of textual data is encountered."""
self.current_data.append(data)
Expand Down Expand Up @@ -769,7 +789,9 @@ def __init__(self, *args, **kwargs):
kwargs['features'] = 'xml'
warnings.warn(
'The BeautifulStoneSoup class is deprecated. Instead of using '
'it, pass features="xml" into the BeautifulSoup constructor.')
'it, pass features="xml" into the BeautifulSoup constructor.',
DeprecationWarning, stacklevel=2
)
super(BeautifulStoneSoup, self).__init__(*args, **kwargs)


Expand Down

0 comments on commit 671a443

Please sign in to comment.