Format: text/x-python
⬇ Download File (3.4 KB)
   1  # Copyright 2010-2023 Kurt McKee <contactme@kurtmckee.org>
   2  # Copyright 2002-2008 Mark Pilgrim
   3  # All rights reserved.
   4  #
   5  # This file is a part of feedparser.
   6  #
   7  # Redistribution and use in source and binary forms, with or without
   8  # modification, are permitted provided that the following conditions are met:
   9  #
  10  # * Redistributions of source code must retain the above copyright notice,
  11  #   this list of conditions and the following disclaimer.
  12  # * Redistributions in binary form must reproduce the above copyright notice,
  13  #   this list of conditions and the following disclaimer in the documentation
  14  #   and/or other materials provided with the distribution.
  15  #
  16  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
  17  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  20  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26  # POSSIBILITY OF SUCH DAMAGE.
  27  
  28  import re
  29  
  30  import sgmllib
  31  
  32  __all__ = [
  33      'sgmllib',
  34      'charref',
  35      'tagfind',
  36      'attrfind',
  37      'entityref',
  38      'incomplete',
  39      'interesting',
  40      'shorttag',
  41      'shorttagopen',
  42      'starttagopen',
  43      'endbracket',
  44  ]
  45  
  46  # sgmllib defines a number of module-level regular expressions that are
  47  # insufficient for the XML parsing feedparser needs. Rather than modify
  48  # the variables directly in sgmllib, they're defined here using the same
  49  # names, and the compiled code objects of several sgmllib.SGMLParser
  50  # methods are copied into _BaseHTMLProcessor so that they execute in
  51  # feedparser's scope instead of sgmllib's scope.
  52  charref = re.compile(r'&#(\d+|[xX][0-9a-fA-F]+);')
  53  tagfind = re.compile(r'[a-zA-Z][-_.:a-zA-Z0-9]*')
  54  attrfind = re.compile(
  55      r"""\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)[$]?(\s*=\s*"""
  56      r"""('[^']*'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$()_#=~'"@]*))?"""
  57  )
  58  
  59  # Unfortunately, these must be copied over to prevent NameError exceptions
  60  entityref = sgmllib.entityref
  61  incomplete = sgmllib.incomplete
  62  interesting = sgmllib.interesting
  63  shorttag = sgmllib.shorttag
  64  shorttagopen = sgmllib.shorttagopen
  65  starttagopen = sgmllib.starttagopen
  66  
  67  
  68  class _EndBracketRegEx:
  69      def __init__(self):
  70          # Overriding the built-in sgmllib.endbracket regex allows the
  71          # parser to find angle brackets embedded in element attributes.
  72          self.endbracket = re.compile(
  73              r'('
  74              r"""[^'"<>]"""
  75              r"""|"[^"]*"(?=>|/|\s|\w+=)"""
  76              r"""|'[^']*'(?=>|/|\s|\w+=))*(?=[<>])"""
  77              r"""|.*?(?=[<>]"""
  78              r')'
  79          )
  80  
  81      def search(self, target, index=0):
  82          match = self.endbracket.match(target, index)
  83          if match is not None:
  84              # Returning a new object in the calling thread's context
  85              # resolves a thread-safety.
  86              return EndBracketMatch(match)
  87          return None
  88  
  89  
  90  class EndBracketMatch:
  91      def __init__(self, match):
  92          self.match = match
  93  
  94      def start(self, n):
  95          return self.match.end(n)
  96  
  97  
  98  endbracket = _EndBracketRegEx()
  99