lxml 5.2.0__cp310-cp310-win32.whl → 5.2.2__cp310-cp310-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lxml/ElementInclude.py +244 -244
- lxml/__init__.py +22 -22
- lxml/_elementpath.cp310-win32.pyd +0 -0
- lxml/_elementpath.py +341 -341
- lxml/apihelpers.pxi +1793 -1793
- lxml/builder.cp310-win32.pyd +0 -0
- lxml/builder.py +232 -232
- lxml/classlookup.pxi +580 -580
- lxml/cleanup.pxi +215 -215
- lxml/cssselect.py +101 -101
- lxml/debug.pxi +90 -90
- lxml/docloader.pxi +178 -178
- lxml/doctestcompare.py +488 -488
- lxml/dtd.pxi +478 -478
- lxml/etree.cp310-win32.pyd +0 -0
- lxml/etree.h +6 -6
- lxml/etree.pyx +3732 -3711
- lxml/extensions.pxi +833 -833
- lxml/html/ElementSoup.py +10 -10
- lxml/html/__init__.py +1923 -1923
- lxml/html/_diffcommand.py +86 -86
- lxml/html/_html5builder.py +100 -100
- lxml/html/_setmixin.py +56 -56
- lxml/html/builder.py +133 -133
- lxml/html/clean.py +21 -21
- lxml/html/defs.py +135 -135
- lxml/html/diff.cp310-win32.pyd +0 -0
- lxml/html/diff.py +878 -878
- lxml/html/formfill.py +299 -299
- lxml/html/html5parser.py +260 -260
- lxml/html/soupparser.py +314 -314
- lxml/html/usedoctest.py +13 -13
- lxml/includes/c14n.pxd +25 -25
- lxml/includes/config.pxd +3 -3
- lxml/includes/dtdvalid.pxd +18 -18
- lxml/includes/etree_defs.h +379 -379
- lxml/includes/etreepublic.pxd +237 -237
- lxml/includes/htmlparser.pxd +56 -56
- lxml/includes/lxml-version.h +1 -1
- lxml/includes/relaxng.pxd +64 -64
- lxml/includes/schematron.pxd +34 -34
- lxml/includes/tree.pxd +494 -494
- lxml/includes/uri.pxd +5 -5
- lxml/includes/xinclude.pxd +22 -22
- lxml/includes/xmlerror.pxd +852 -852
- lxml/includes/xmlparser.pxd +265 -265
- lxml/includes/xmlschema.pxd +35 -35
- lxml/includes/xpath.pxd +136 -136
- lxml/includes/xslt.pxd +190 -190
- lxml/isoschematron/__init__.py +348 -348
- lxml/isoschematron/resources/rng/iso-schematron.rng +709 -709
- lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl +75 -75
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl +312 -312
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl +1159 -1159
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl +54 -54
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl +1796 -1796
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl +588 -588
- lxml/iterparse.pxi +438 -438
- lxml/lxml.etree.h +6 -6
- lxml/nsclasses.pxi +281 -281
- lxml/objectify.cp310-win32.pyd +0 -0
- lxml/objectify.pyx +2145 -2145
- lxml/objectpath.pxi +332 -332
- lxml/parser.pxi +1994 -1994
- lxml/parsertarget.pxi +180 -180
- lxml/proxy.pxi +619 -619
- lxml/public-api.pxi +178 -178
- lxml/pyclasslookup.py +3 -3
- lxml/readonlytree.pxi +565 -565
- lxml/relaxng.pxi +165 -165
- lxml/sax.cp310-win32.pyd +0 -0
- lxml/sax.py +275 -275
- lxml/saxparser.pxi +875 -875
- lxml/schematron.pxi +168 -168
- lxml/serializer.pxi +1871 -1871
- lxml/usedoctest.py +13 -13
- lxml/xinclude.pxi +67 -67
- lxml/xmlerror.pxi +1654 -1654
- lxml/xmlid.pxi +179 -179
- lxml/xmlschema.pxi +215 -215
- lxml/xpath.pxi +487 -487
- lxml/xslt.pxi +950 -950
- lxml/xsltext.pxi +242 -242
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/LICENSE.txt +29 -29
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/LICENSES.txt +29 -29
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/METADATA +9 -17
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/RECORD +89 -89
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/WHEEL +0 -0
- {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/top_level.txt +0 -0
lxml/html/_diffcommand.py
CHANGED
@@ -1,86 +1,86 @@
|
|
1
|
-
import optparse
|
2
|
-
import sys
|
3
|
-
import re
|
4
|
-
import os
|
5
|
-
from .diff import htmldiff
|
6
|
-
|
7
|
-
description = """\
|
8
|
-
"""
|
9
|
-
|
10
|
-
parser = optparse.OptionParser(
|
11
|
-
usage="%prog [OPTIONS] FILE1 FILE2\n"
|
12
|
-
"%prog --annotate [OPTIONS] INFO1 FILE1 INFO2 FILE2 ...",
|
13
|
-
description=description,
|
14
|
-
)
|
15
|
-
|
16
|
-
parser.add_option(
|
17
|
-
'-o', '--output',
|
18
|
-
metavar="FILE",
|
19
|
-
dest="output",
|
20
|
-
default="-",
|
21
|
-
help="File to write the difference to",
|
22
|
-
)
|
23
|
-
|
24
|
-
parser.add_option(
|
25
|
-
'-a', '--annotation',
|
26
|
-
action="store_true",
|
27
|
-
dest="annotation",
|
28
|
-
help="Do an annotation")
|
29
|
-
|
30
|
-
def main(args=None):
|
31
|
-
if args is None:
|
32
|
-
args = sys.argv[1:]
|
33
|
-
options, args = parser.parse_args(args)
|
34
|
-
if options.annotation:
|
35
|
-
return annotate(options, args)
|
36
|
-
if len(args) != 2:
|
37
|
-
print('Error: you must give two files')
|
38
|
-
parser.print_help()
|
39
|
-
sys.exit(1)
|
40
|
-
file1, file2 = args
|
41
|
-
input1 = read_file(file1)
|
42
|
-
input2 = read_file(file2)
|
43
|
-
body1 = split_body(input1)[1]
|
44
|
-
pre, body2, post = split_body(input2)
|
45
|
-
result = htmldiff(body1, body2)
|
46
|
-
result = pre + result + post
|
47
|
-
if options.output == '-':
|
48
|
-
if not result.endswith('\n'):
|
49
|
-
result += '\n'
|
50
|
-
sys.stdout.write(result)
|
51
|
-
else:
|
52
|
-
with open(options.output, 'wb') as f:
|
53
|
-
f.write(result)
|
54
|
-
|
55
|
-
def read_file(filename):
|
56
|
-
if filename == '-':
|
57
|
-
c = sys.stdin.read()
|
58
|
-
elif not os.path.exists(filename):
|
59
|
-
raise OSError(
|
60
|
-
"Input file %s does not exist" % filename)
|
61
|
-
else:
|
62
|
-
with open(filename, 'rb') as f:
|
63
|
-
c = f.read()
|
64
|
-
return c
|
65
|
-
|
66
|
-
body_start_re = re.compile(
|
67
|
-
r"<body.*?>", re.I|re.S)
|
68
|
-
body_end_re = re.compile(
|
69
|
-
r"</body.*?>", re.I|re.S)
|
70
|
-
|
71
|
-
def split_body(html):
|
72
|
-
pre = post = ''
|
73
|
-
match = body_start_re.search(html)
|
74
|
-
if match:
|
75
|
-
pre = html[:match.end()]
|
76
|
-
html = html[match.end():]
|
77
|
-
match = body_end_re.search(html)
|
78
|
-
if match:
|
79
|
-
post = html[match.start():]
|
80
|
-
html = html[:match.start()]
|
81
|
-
return pre, html, post
|
82
|
-
|
83
|
-
def annotate(options, args):
|
84
|
-
print("Not yet implemented")
|
85
|
-
sys.exit(1)
|
86
|
-
|
1
|
+
import optparse
|
2
|
+
import sys
|
3
|
+
import re
|
4
|
+
import os
|
5
|
+
from .diff import htmldiff
|
6
|
+
|
7
|
+
description = """\
|
8
|
+
"""
|
9
|
+
|
10
|
+
parser = optparse.OptionParser(
|
11
|
+
usage="%prog [OPTIONS] FILE1 FILE2\n"
|
12
|
+
"%prog --annotate [OPTIONS] INFO1 FILE1 INFO2 FILE2 ...",
|
13
|
+
description=description,
|
14
|
+
)
|
15
|
+
|
16
|
+
parser.add_option(
|
17
|
+
'-o', '--output',
|
18
|
+
metavar="FILE",
|
19
|
+
dest="output",
|
20
|
+
default="-",
|
21
|
+
help="File to write the difference to",
|
22
|
+
)
|
23
|
+
|
24
|
+
parser.add_option(
|
25
|
+
'-a', '--annotation',
|
26
|
+
action="store_true",
|
27
|
+
dest="annotation",
|
28
|
+
help="Do an annotation")
|
29
|
+
|
30
|
+
def main(args=None):
|
31
|
+
if args is None:
|
32
|
+
args = sys.argv[1:]
|
33
|
+
options, args = parser.parse_args(args)
|
34
|
+
if options.annotation:
|
35
|
+
return annotate(options, args)
|
36
|
+
if len(args) != 2:
|
37
|
+
print('Error: you must give two files')
|
38
|
+
parser.print_help()
|
39
|
+
sys.exit(1)
|
40
|
+
file1, file2 = args
|
41
|
+
input1 = read_file(file1)
|
42
|
+
input2 = read_file(file2)
|
43
|
+
body1 = split_body(input1)[1]
|
44
|
+
pre, body2, post = split_body(input2)
|
45
|
+
result = htmldiff(body1, body2)
|
46
|
+
result = pre + result + post
|
47
|
+
if options.output == '-':
|
48
|
+
if not result.endswith('\n'):
|
49
|
+
result += '\n'
|
50
|
+
sys.stdout.write(result)
|
51
|
+
else:
|
52
|
+
with open(options.output, 'wb') as f:
|
53
|
+
f.write(result)
|
54
|
+
|
55
|
+
def read_file(filename):
|
56
|
+
if filename == '-':
|
57
|
+
c = sys.stdin.read()
|
58
|
+
elif not os.path.exists(filename):
|
59
|
+
raise OSError(
|
60
|
+
"Input file %s does not exist" % filename)
|
61
|
+
else:
|
62
|
+
with open(filename, 'rb') as f:
|
63
|
+
c = f.read()
|
64
|
+
return c
|
65
|
+
|
66
|
+
body_start_re = re.compile(
|
67
|
+
r"<body.*?>", re.I|re.S)
|
68
|
+
body_end_re = re.compile(
|
69
|
+
r"</body.*?>", re.I|re.S)
|
70
|
+
|
71
|
+
def split_body(html):
|
72
|
+
pre = post = ''
|
73
|
+
match = body_start_re.search(html)
|
74
|
+
if match:
|
75
|
+
pre = html[:match.end()]
|
76
|
+
html = html[match.end():]
|
77
|
+
match = body_end_re.search(html)
|
78
|
+
if match:
|
79
|
+
post = html[match.start():]
|
80
|
+
html = html[:match.start()]
|
81
|
+
return pre, html, post
|
82
|
+
|
83
|
+
def annotate(options, args):
|
84
|
+
print("Not yet implemented")
|
85
|
+
sys.exit(1)
|
86
|
+
|
lxml/html/_html5builder.py
CHANGED
@@ -1,100 +1,100 @@
|
|
1
|
-
"""
|
2
|
-
Legacy module - don't use in new code!
|
3
|
-
|
4
|
-
html5lib now has its own proper implementation.
|
5
|
-
|
6
|
-
This module implements a tree builder for html5lib that generates lxml
|
7
|
-
html element trees. This module uses camelCase as it follows the
|
8
|
-
html5lib style guide.
|
9
|
-
"""
|
10
|
-
|
11
|
-
from html5lib.treebuilders import _base, etree as etree_builders
|
12
|
-
from lxml import html, etree
|
13
|
-
|
14
|
-
|
15
|
-
class DocumentType:
|
16
|
-
|
17
|
-
def __init__(self, name, publicId, systemId):
|
18
|
-
self.name = name
|
19
|
-
self.publicId = publicId
|
20
|
-
self.systemId = systemId
|
21
|
-
|
22
|
-
class Document:
|
23
|
-
|
24
|
-
def __init__(self):
|
25
|
-
self._elementTree = None
|
26
|
-
self.childNodes = []
|
27
|
-
|
28
|
-
def appendChild(self, element):
|
29
|
-
self._elementTree.getroot().addnext(element._element)
|
30
|
-
|
31
|
-
|
32
|
-
class TreeBuilder(_base.TreeBuilder):
|
33
|
-
documentClass = Document
|
34
|
-
doctypeClass = DocumentType
|
35
|
-
elementClass = None
|
36
|
-
commentClass = None
|
37
|
-
fragmentClass = Document
|
38
|
-
|
39
|
-
def __init__(self, *args, **kwargs):
|
40
|
-
html_builder = etree_builders.getETreeModule(html, fullTree=False)
|
41
|
-
etree_builder = etree_builders.getETreeModule(etree, fullTree=False)
|
42
|
-
self.elementClass = html_builder.Element
|
43
|
-
self.commentClass = etree_builder.Comment
|
44
|
-
_base.TreeBuilder.__init__(self, *args, **kwargs)
|
45
|
-
|
46
|
-
def reset(self):
|
47
|
-
_base.TreeBuilder.reset(self)
|
48
|
-
self.rootInserted = False
|
49
|
-
self.initialComments = []
|
50
|
-
self.doctype = None
|
51
|
-
|
52
|
-
def getDocument(self):
|
53
|
-
return self.document._elementTree
|
54
|
-
|
55
|
-
def getFragment(self):
|
56
|
-
fragment = []
|
57
|
-
element = self.openElements[0]._element
|
58
|
-
if element.text:
|
59
|
-
fragment.append(element.text)
|
60
|
-
fragment.extend(element.getchildren())
|
61
|
-
if element.tail:
|
62
|
-
fragment.append(element.tail)
|
63
|
-
return fragment
|
64
|
-
|
65
|
-
def insertDoctype(self, name, publicId, systemId):
|
66
|
-
doctype = self.doctypeClass(name, publicId, systemId)
|
67
|
-
self.doctype = doctype
|
68
|
-
|
69
|
-
def insertComment(self, data, parent=None):
|
70
|
-
if not self.rootInserted:
|
71
|
-
self.initialComments.append(data)
|
72
|
-
else:
|
73
|
-
_base.TreeBuilder.insertComment(self, data, parent)
|
74
|
-
|
75
|
-
def insertRoot(self, name):
|
76
|
-
buf = []
|
77
|
-
if self.doctype and self.doctype.name:
|
78
|
-
buf.append('<!DOCTYPE %s' % self.doctype.name)
|
79
|
-
if self.doctype.publicId is not None or self.doctype.systemId is not None:
|
80
|
-
buf.append(' PUBLIC "%s" "%s"' % (self.doctype.publicId,
|
81
|
-
self.doctype.systemId))
|
82
|
-
buf.append('>')
|
83
|
-
buf.append('<html></html>')
|
84
|
-
root = html.fromstring(''.join(buf))
|
85
|
-
|
86
|
-
# Append the initial comments:
|
87
|
-
for comment in self.initialComments:
|
88
|
-
root.addprevious(etree.Comment(comment))
|
89
|
-
|
90
|
-
# Create the root document and add the ElementTree to it
|
91
|
-
self.document = self.documentClass()
|
92
|
-
self.document._elementTree = root.getroottree()
|
93
|
-
|
94
|
-
# Add the root element to the internal child/open data structures
|
95
|
-
root_element = self.elementClass(name)
|
96
|
-
root_element._element = root
|
97
|
-
self.document.childNodes.append(root_element)
|
98
|
-
self.openElements.append(root_element)
|
99
|
-
|
100
|
-
self.rootInserted = True
|
1
|
+
"""
|
2
|
+
Legacy module - don't use in new code!
|
3
|
+
|
4
|
+
html5lib now has its own proper implementation.
|
5
|
+
|
6
|
+
This module implements a tree builder for html5lib that generates lxml
|
7
|
+
html element trees. This module uses camelCase as it follows the
|
8
|
+
html5lib style guide.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from html5lib.treebuilders import _base, etree as etree_builders
|
12
|
+
from lxml import html, etree
|
13
|
+
|
14
|
+
|
15
|
+
class DocumentType:
|
16
|
+
|
17
|
+
def __init__(self, name, publicId, systemId):
|
18
|
+
self.name = name
|
19
|
+
self.publicId = publicId
|
20
|
+
self.systemId = systemId
|
21
|
+
|
22
|
+
class Document:
|
23
|
+
|
24
|
+
def __init__(self):
|
25
|
+
self._elementTree = None
|
26
|
+
self.childNodes = []
|
27
|
+
|
28
|
+
def appendChild(self, element):
|
29
|
+
self._elementTree.getroot().addnext(element._element)
|
30
|
+
|
31
|
+
|
32
|
+
class TreeBuilder(_base.TreeBuilder):
|
33
|
+
documentClass = Document
|
34
|
+
doctypeClass = DocumentType
|
35
|
+
elementClass = None
|
36
|
+
commentClass = None
|
37
|
+
fragmentClass = Document
|
38
|
+
|
39
|
+
def __init__(self, *args, **kwargs):
|
40
|
+
html_builder = etree_builders.getETreeModule(html, fullTree=False)
|
41
|
+
etree_builder = etree_builders.getETreeModule(etree, fullTree=False)
|
42
|
+
self.elementClass = html_builder.Element
|
43
|
+
self.commentClass = etree_builder.Comment
|
44
|
+
_base.TreeBuilder.__init__(self, *args, **kwargs)
|
45
|
+
|
46
|
+
def reset(self):
|
47
|
+
_base.TreeBuilder.reset(self)
|
48
|
+
self.rootInserted = False
|
49
|
+
self.initialComments = []
|
50
|
+
self.doctype = None
|
51
|
+
|
52
|
+
def getDocument(self):
|
53
|
+
return self.document._elementTree
|
54
|
+
|
55
|
+
def getFragment(self):
|
56
|
+
fragment = []
|
57
|
+
element = self.openElements[0]._element
|
58
|
+
if element.text:
|
59
|
+
fragment.append(element.text)
|
60
|
+
fragment.extend(element.getchildren())
|
61
|
+
if element.tail:
|
62
|
+
fragment.append(element.tail)
|
63
|
+
return fragment
|
64
|
+
|
65
|
+
def insertDoctype(self, name, publicId, systemId):
|
66
|
+
doctype = self.doctypeClass(name, publicId, systemId)
|
67
|
+
self.doctype = doctype
|
68
|
+
|
69
|
+
def insertComment(self, data, parent=None):
|
70
|
+
if not self.rootInserted:
|
71
|
+
self.initialComments.append(data)
|
72
|
+
else:
|
73
|
+
_base.TreeBuilder.insertComment(self, data, parent)
|
74
|
+
|
75
|
+
def insertRoot(self, name):
|
76
|
+
buf = []
|
77
|
+
if self.doctype and self.doctype.name:
|
78
|
+
buf.append('<!DOCTYPE %s' % self.doctype.name)
|
79
|
+
if self.doctype.publicId is not None or self.doctype.systemId is not None:
|
80
|
+
buf.append(' PUBLIC "%s" "%s"' % (self.doctype.publicId,
|
81
|
+
self.doctype.systemId))
|
82
|
+
buf.append('>')
|
83
|
+
buf.append('<html></html>')
|
84
|
+
root = html.fromstring(''.join(buf))
|
85
|
+
|
86
|
+
# Append the initial comments:
|
87
|
+
for comment in self.initialComments:
|
88
|
+
root.addprevious(etree.Comment(comment))
|
89
|
+
|
90
|
+
# Create the root document and add the ElementTree to it
|
91
|
+
self.document = self.documentClass()
|
92
|
+
self.document._elementTree = root.getroottree()
|
93
|
+
|
94
|
+
# Add the root element to the internal child/open data structures
|
95
|
+
root_element = self.elementClass(name)
|
96
|
+
root_element._element = root
|
97
|
+
self.document.childNodes.append(root_element)
|
98
|
+
self.openElements.append(root_element)
|
99
|
+
|
100
|
+
self.rootInserted = True
|
lxml/html/_setmixin.py
CHANGED
@@ -1,56 +1,56 @@
|
|
1
|
-
try:
|
2
|
-
from collections.abc import MutableSet
|
3
|
-
except ImportError:
|
4
|
-
from collections.abc import MutableSet
|
5
|
-
|
6
|
-
|
7
|
-
class SetMixin(MutableSet):
|
8
|
-
|
9
|
-
"""
|
10
|
-
Mix-in for sets. You must define __iter__, add, remove
|
11
|
-
"""
|
12
|
-
|
13
|
-
def __len__(self):
|
14
|
-
length = 0
|
15
|
-
for item in self:
|
16
|
-
length += 1
|
17
|
-
return length
|
18
|
-
|
19
|
-
def __contains__(self, item):
|
20
|
-
for has_item in self:
|
21
|
-
if item == has_item:
|
22
|
-
return True
|
23
|
-
return False
|
24
|
-
|
25
|
-
issubset = MutableSet.__le__
|
26
|
-
issuperset = MutableSet.__ge__
|
27
|
-
|
28
|
-
union = MutableSet.__or__
|
29
|
-
intersection = MutableSet.__and__
|
30
|
-
difference = MutableSet.__sub__
|
31
|
-
symmetric_difference = MutableSet.__xor__
|
32
|
-
|
33
|
-
def copy(self):
|
34
|
-
return set(self)
|
35
|
-
|
36
|
-
def update(self, other):
|
37
|
-
self |= other
|
38
|
-
|
39
|
-
def intersection_update(self, other):
|
40
|
-
self &= other
|
41
|
-
|
42
|
-
def difference_update(self, other):
|
43
|
-
self -= other
|
44
|
-
|
45
|
-
def symmetric_difference_update(self, other):
|
46
|
-
self ^= other
|
47
|
-
|
48
|
-
def discard(self, item):
|
49
|
-
try:
|
50
|
-
self.remove(item)
|
51
|
-
except KeyError:
|
52
|
-
pass
|
53
|
-
|
54
|
-
@classmethod
|
55
|
-
def _from_iterable(cls, it):
|
56
|
-
return set(it)
|
1
|
+
try:
|
2
|
+
from collections.abc import MutableSet
|
3
|
+
except ImportError:
|
4
|
+
from collections.abc import MutableSet
|
5
|
+
|
6
|
+
|
7
|
+
class SetMixin(MutableSet):
|
8
|
+
|
9
|
+
"""
|
10
|
+
Mix-in for sets. You must define __iter__, add, remove
|
11
|
+
"""
|
12
|
+
|
13
|
+
def __len__(self):
|
14
|
+
length = 0
|
15
|
+
for item in self:
|
16
|
+
length += 1
|
17
|
+
return length
|
18
|
+
|
19
|
+
def __contains__(self, item):
|
20
|
+
for has_item in self:
|
21
|
+
if item == has_item:
|
22
|
+
return True
|
23
|
+
return False
|
24
|
+
|
25
|
+
issubset = MutableSet.__le__
|
26
|
+
issuperset = MutableSet.__ge__
|
27
|
+
|
28
|
+
union = MutableSet.__or__
|
29
|
+
intersection = MutableSet.__and__
|
30
|
+
difference = MutableSet.__sub__
|
31
|
+
symmetric_difference = MutableSet.__xor__
|
32
|
+
|
33
|
+
def copy(self):
|
34
|
+
return set(self)
|
35
|
+
|
36
|
+
def update(self, other):
|
37
|
+
self |= other
|
38
|
+
|
39
|
+
def intersection_update(self, other):
|
40
|
+
self &= other
|
41
|
+
|
42
|
+
def difference_update(self, other):
|
43
|
+
self -= other
|
44
|
+
|
45
|
+
def symmetric_difference_update(self, other):
|
46
|
+
self ^= other
|
47
|
+
|
48
|
+
def discard(self, item):
|
49
|
+
try:
|
50
|
+
self.remove(item)
|
51
|
+
except KeyError:
|
52
|
+
pass
|
53
|
+
|
54
|
+
@classmethod
|
55
|
+
def _from_iterable(cls, it):
|
56
|
+
return set(it)
|