mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Foo and fo
This commit is contained in:
parent
b278ee83c5
commit
fbd42228f8
|
@ -15,9 +15,6 @@ This file lists bundled packages and their associated licensing terms.
|
||||||
Copyright (C) 2013, Jonathan Hartley.
|
Copyright (C) 2013, Jonathan Hartley.
|
||||||
* The Fcrypt library located under thirdparty/fcrypt/.
|
* The Fcrypt library located under thirdparty/fcrypt/.
|
||||||
Copyright (C) 2000, 2001, 2004 Carey Evans.
|
Copyright (C) 2000, 2001, 2004 Carey Evans.
|
||||||
* The Oset library located under thirdparty/oset/.
|
|
||||||
Copyright (C) 2010, BlueDynamics Alliance, Austria.
|
|
||||||
Copyright (C) 2009, Raymond Hettinger, and others.
|
|
||||||
* The PrettyPrint library located under thirdparty/prettyprint/.
|
* The PrettyPrint library located under thirdparty/prettyprint/.
|
||||||
Copyright (C) 2010, Chris Hall.
|
Copyright (C) 2010, Chris Hall.
|
||||||
* The SocksiPy library located under thirdparty/socks/.
|
* The SocksiPy library located under thirdparty/socks/.
|
||||||
|
|
|
@ -5,6 +5,7 @@ Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
@ -140,3 +141,61 @@ class LRUDict(object):
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return self.cache.keys()
|
return self.cache.keys()
|
||||||
|
|
||||||
|
# Reference: https://code.activestate.com/recipes/576694/
|
||||||
|
class OrderedSet(collections.MutableSet):
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.end = end = []
|
||||||
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
|
self.map = {} # key --> [key, prev, next]
|
||||||
|
if iterable is not None:
|
||||||
|
self |= iterable
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.map)
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.map
|
||||||
|
|
||||||
|
def add(self, key):
|
||||||
|
if key not in self.map:
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
curr[2] = end[1] = self.map[key] = [key, curr, end]
|
||||||
|
|
||||||
|
def discard(self, key):
|
||||||
|
if key in self.map:
|
||||||
|
key, prev, next = self.map.pop(key)
|
||||||
|
prev[2] = next
|
||||||
|
next[1] = prev
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[2]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[2]
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[1]
|
||||||
|
|
||||||
|
def pop(self, last=True):
|
||||||
|
if not self:
|
||||||
|
raise KeyError('set is empty')
|
||||||
|
key = self.end[1][0] if last else self.end[2][0]
|
||||||
|
self.discard(key)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self:
|
||||||
|
return '%s()' % (self.__class__.__name__,)
|
||||||
|
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, OrderedSet):
|
||||||
|
return len(self) == len(other) and list(self) == list(other)
|
||||||
|
return set(self) == set(other)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import urllib2
|
|
||||||
|
|
||||||
import lib.controller.checks
|
import lib.controller.checks
|
||||||
import lib.core.common
|
import lib.core.common
|
||||||
|
@ -66,6 +65,7 @@ from lib.core.data import mergedOptions
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.datatype import AttribDict
|
from lib.core.datatype import AttribDict
|
||||||
from lib.core.datatype import InjectionDict
|
from lib.core.datatype import InjectionDict
|
||||||
|
from lib.core.datatype import OrderedSet
|
||||||
from lib.core.defaults import defaults
|
from lib.core.defaults import defaults
|
||||||
from lib.core.dicts import DBMS_DICT
|
from lib.core.dicts import DBMS_DICT
|
||||||
from lib.core.dicts import DUMP_REPLACEMENTS
|
from lib.core.dicts import DUMP_REPLACEMENTS
|
||||||
|
@ -149,7 +149,6 @@ from lib.utils.search import search
|
||||||
from lib.utils.purge import purge
|
from lib.utils.purge import purge
|
||||||
from thirdparty.keepalive import keepalive
|
from thirdparty.keepalive import keepalive
|
||||||
from thirdparty.multipart import multipartpost
|
from thirdparty.multipart import multipartpost
|
||||||
from thirdparty.oset.pyoset import oset
|
|
||||||
from thirdparty.six.moves import http_client as _http_client
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
from thirdparty.six.moves import http_cookiejar as _http_cookiejar
|
from thirdparty.six.moves import http_cookiejar as _http_cookiejar
|
||||||
from thirdparty.six.moves import urllib as _urllib
|
from thirdparty.six.moves import urllib as _urllib
|
||||||
|
@ -2023,7 +2022,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||||
kb.preprocessFunctions = []
|
kb.preprocessFunctions = []
|
||||||
kb.skipVulnHost = None
|
kb.skipVulnHost = None
|
||||||
kb.tamperFunctions = []
|
kb.tamperFunctions = []
|
||||||
kb.targets = oset()
|
kb.targets = OrderedSet()
|
||||||
kb.testedParams = set()
|
kb.testedParams = set()
|
||||||
kb.userAgents = None
|
kb.userAgents = None
|
||||||
kb.vainRun = True
|
kb.vainRun = True
|
||||||
|
|
|
@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.3.3.60"
|
VERSION = "1.3.3.61"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Popen(subprocess.Popen):
|
||||||
getattr(self, which).close()
|
getattr(self, which).close()
|
||||||
setattr(self, which, None)
|
setattr(self, which, None)
|
||||||
|
|
||||||
if subprocess.mswindows:
|
if IS_WIN:
|
||||||
def send(self, input):
|
def send(self, input):
|
||||||
if not self.stdin:
|
if not self.stdin:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -10,9 +10,9 @@ import re
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.datatype import OrderedSet
|
||||||
from lib.core.exception import SqlmapSyntaxException
|
from lib.core.exception import SqlmapSyntaxException
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from thirdparty.oset.pyoset import oset
|
|
||||||
from thirdparty.six.moves import http_client as _http_client
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
|
|
||||||
abortedFlag = None
|
abortedFlag = None
|
||||||
|
@ -26,7 +26,7 @@ def parseSitemap(url, retVal=None):
|
||||||
try:
|
try:
|
||||||
if retVal is None:
|
if retVal is None:
|
||||||
abortedFlag = False
|
abortedFlag = False
|
||||||
retVal = oset()
|
retVal = OrderedSet()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
|
content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
|
||||||
|
|
|
@ -37,6 +37,7 @@ from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
|
from lib.core.datatype import OrderedSet
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
|
@ -50,7 +51,6 @@ from lib.core.settings import SHELL_RUNCMD_EXE_TAG
|
||||||
from lib.core.settings import SHELL_WRITABLE_DIR_TAG
|
from lib.core.settings import SHELL_WRITABLE_DIR_TAG
|
||||||
from lib.core.settings import VIEWSTATE_REGEX
|
from lib.core.settings import VIEWSTATE_REGEX
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from thirdparty.oset.pyoset import oset
|
|
||||||
from thirdparty.six.moves import urllib as _urllib
|
from thirdparty.six.moves import urllib as _urllib
|
||||||
|
|
||||||
class Web:
|
class Web:
|
||||||
|
@ -254,7 +254,7 @@ class Web:
|
||||||
|
|
||||||
directories = list(arrayizeValue(getManualDirectories()))
|
directories = list(arrayizeValue(getManualDirectories()))
|
||||||
directories.extend(getAutoDirectories())
|
directories.extend(getAutoDirectories())
|
||||||
directories = list(oset(directories))
|
directories = list(OrderedSet(directories))
|
||||||
|
|
||||||
path = _urllib.parse.urlparse(conf.url).path or '/'
|
path = _urllib.parse.urlparse(conf.url).path or '/'
|
||||||
path = re.sub(r"/[^/]*\.\w+\Z", '/', path)
|
path = re.sub(r"/[^/]*\.\w+\Z", '/', path)
|
||||||
|
|
|
@ -22,6 +22,7 @@ from lib.core.common import urldecode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.datatype import OrderedSet
|
||||||
from lib.core.enums import MKSTEMP_PREFIX
|
from lib.core.enums import MKSTEMP_PREFIX
|
||||||
from lib.core.exception import SqlmapConnectionException
|
from lib.core.exception import SqlmapConnectionException
|
||||||
from lib.core.exception import SqlmapSyntaxException
|
from lib.core.exception import SqlmapSyntaxException
|
||||||
|
@ -31,7 +32,6 @@ from lib.core.threads import runThreads
|
||||||
from lib.parse.sitemap import parseSitemap
|
from lib.parse.sitemap import parseSitemap
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from thirdparty.beautifulsoup.beautifulsoup import BeautifulSoup
|
from thirdparty.beautifulsoup.beautifulsoup import BeautifulSoup
|
||||||
from thirdparty.oset.pyoset import oset
|
|
||||||
from thirdparty.six.moves import http_client as _http_client
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
from thirdparty.six.moves import urllib as _urllib
|
from thirdparty.six.moves import urllib as _urllib
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ def crawl(target):
|
||||||
try:
|
try:
|
||||||
visited = set()
|
visited = set()
|
||||||
threadData = getCurrentThreadData()
|
threadData = getCurrentThreadData()
|
||||||
threadData.shared.value = oset()
|
threadData.shared.value = OrderedSet()
|
||||||
|
|
||||||
def crawlThread():
|
def crawlThread():
|
||||||
threadData = getCurrentThreadData()
|
threadData = getCurrentThreadData()
|
||||||
|
|
|
@ -45,7 +45,6 @@ from hashlib import sha224
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from hashlib import sha384
|
from hashlib import sha384
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
from Queue import Queue
|
|
||||||
|
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
from lib.core.common import checkFile
|
from lib.core.common import checkFile
|
||||||
|
@ -68,6 +67,7 @@ from lib.core.convert import utf8encode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.datatype import OrderedSet
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HASH
|
from lib.core.enums import HASH
|
||||||
from lib.core.enums import MKSTEMP_PREFIX
|
from lib.core.enums import MKSTEMP_PREFIX
|
||||||
|
@ -87,9 +87,9 @@ from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.settings import ROTATING_CHARS
|
from lib.core.settings import ROTATING_CHARS
|
||||||
from lib.core.wordlist import Wordlist
|
from lib.core.wordlist import Wordlist
|
||||||
from thirdparty.colorama.initialise import init as coloramainit
|
from thirdparty.colorama.initialise import init as coloramainit
|
||||||
from thirdparty.oset.pyoset import oset
|
|
||||||
from thirdparty.pydes.pyDes import des
|
from thirdparty.pydes.pyDes import des
|
||||||
from thirdparty.pydes.pyDes import CBC
|
from thirdparty.pydes.pyDes import CBC
|
||||||
|
from thirdparty.six.moves import queue as _queue
|
||||||
|
|
||||||
def mysql_passwd(password, uppercase=True):
|
def mysql_passwd(password, uppercase=True):
|
||||||
"""
|
"""
|
||||||
|
@ -561,7 +561,7 @@ def storeHashesToFile(attack_dict):
|
||||||
if not attack_dict:
|
if not attack_dict:
|
||||||
return
|
return
|
||||||
|
|
||||||
items = oset()
|
items = OrderedSet()
|
||||||
|
|
||||||
for user, hashes in attack_dict.items():
|
for user, hashes in attack_dict.items():
|
||||||
for hash_ in hashes:
|
for hash_ in hashes:
|
||||||
|
@ -1059,7 +1059,7 @@ def dictionaryAttack(attack_dict):
|
||||||
warnMsg += "not supported on this platform"
|
warnMsg += "not supported on this platform"
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
retVal = Queue()
|
retVal = _queue.Queue()
|
||||||
_bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, 0, 1, kb.wordlists, custom_wordlist, conf.api)
|
_bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, 0, 1, kb.wordlists, custom_wordlist, conf.api)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
@ -1150,7 +1150,7 @@ def dictionaryAttack(attack_dict):
|
||||||
class Value():
|
class Value():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
retVal = Queue()
|
retVal = _queue.Queue()
|
||||||
found_ = Value()
|
found_ = Value()
|
||||||
found_.value = False
|
found_.value = False
|
||||||
|
|
||||||
|
|
29
thirdparty/oset/LICENSE.txt
vendored
29
thirdparty/oset/LICENSE.txt
vendored
|
@ -1,29 +0,0 @@
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
Copyright (c) 2009, Raymond Hettinger, and others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Package structured based on the one developed to odict
|
|
||||||
Copyright (c) 2010, BlueDynamics Alliance, Austria
|
|
||||||
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
* Neither the name of the BlueDynamics Alliance nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from this
|
|
||||||
software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY BlueDynamics Alliance ``AS IS`` AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL BlueDynamics Alliance BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3
thirdparty/oset/__init__.py
vendored
3
thirdparty/oset/__init__.py
vendored
|
@ -1,3 +0,0 @@
|
||||||
"""Main Ordered Set module """
|
|
||||||
|
|
||||||
from pyoset import oset
|
|
476
thirdparty/oset/_abc.py
vendored
476
thirdparty/oset/_abc.py
vendored
|
@ -1,476 +0,0 @@
|
||||||
#!/usr/bin/env python2
|
|
||||||
# -*- mode:python; tab-width: 2; coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""Partially backported python ABC classes"""
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import types
|
|
||||||
|
|
||||||
if sys.version_info > (2, 6):
|
|
||||||
raise ImportError("Use native ABC classes istead of this one.")
|
|
||||||
|
|
||||||
|
|
||||||
# Instance of old-style class
|
|
||||||
class _C:
|
|
||||||
pass
|
|
||||||
|
|
||||||
_InstanceType = type(_C())
|
|
||||||
|
|
||||||
|
|
||||||
def abstractmethod(funcobj):
|
|
||||||
"""A decorator indicating abstract methods.
|
|
||||||
|
|
||||||
Requires that the metaclass is ABCMeta or derived from it. A
|
|
||||||
class that has a metaclass derived from ABCMeta cannot be
|
|
||||||
instantiated unless all of its abstract methods are overridden.
|
|
||||||
The abstract methods can be called using any of the normal
|
|
||||||
'super' call mechanisms.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
class C:
|
|
||||||
__metaclass__ = ABCMeta
|
|
||||||
@abstractmethod
|
|
||||||
def my_abstract_method(self, ...):
|
|
||||||
...
|
|
||||||
"""
|
|
||||||
funcobj.__isabstractmethod__ = True
|
|
||||||
return funcobj
|
|
||||||
|
|
||||||
|
|
||||||
class ABCMeta(type):
|
|
||||||
|
|
||||||
"""Metaclass for defining Abstract Base Classes (ABCs).
|
|
||||||
|
|
||||||
Use this metaclass to create an ABC. An ABC can be subclassed
|
|
||||||
directly, and then acts as a mix-in class. You can also register
|
|
||||||
unrelated concrete classes (even built-in classes) and unrelated
|
|
||||||
ABCs as 'virtual subclasses' -- these and their descendants will
|
|
||||||
be considered subclasses of the registering ABC by the built-in
|
|
||||||
issubclass() function, but the registering ABC won't show up in
|
|
||||||
their MRO (Method Resolution Order) nor will method
|
|
||||||
implementations defined by the registering ABC be callable (not
|
|
||||||
even via super()).
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# A global counter that is incremented each time a class is
|
|
||||||
# registered as a virtual subclass of anything. It forces the
|
|
||||||
# negative cache to be cleared before its next use.
|
|
||||||
_abc_invalidation_counter = 0
|
|
||||||
|
|
||||||
def __new__(mcls, name, bases, namespace):
|
|
||||||
cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
|
|
||||||
# Compute set of abstract method names
|
|
||||||
abstracts = set(name
|
|
||||||
for name, value in namespace.items()
|
|
||||||
if getattr(value, "__isabstractmethod__", False))
|
|
||||||
for base in bases:
|
|
||||||
for name in getattr(base, "__abstractmethods__", set()):
|
|
||||||
value = getattr(cls, name, None)
|
|
||||||
if getattr(value, "__isabstractmethod__", False):
|
|
||||||
abstracts.add(name)
|
|
||||||
cls.__abstractmethods__ = frozenset(abstracts)
|
|
||||||
# Set up inheritance registry
|
|
||||||
cls._abc_registry = set()
|
|
||||||
cls._abc_cache = set()
|
|
||||||
cls._abc_negative_cache = set()
|
|
||||||
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
|
|
||||||
return cls
|
|
||||||
|
|
||||||
def register(cls, subclass):
|
|
||||||
"""Register a virtual subclass of an ABC."""
|
|
||||||
if not isinstance(subclass, (type, types.ClassType)):
|
|
||||||
raise TypeError("Can only register classes")
|
|
||||||
if issubclass(subclass, cls):
|
|
||||||
return # Already a subclass
|
|
||||||
# Subtle: test for cycles *after* testing for "already a subclass";
|
|
||||||
# this means we allow X.register(X) and interpret it as a no-op.
|
|
||||||
if issubclass(cls, subclass):
|
|
||||||
# This would create a cycle, which is bad for the algorithm below
|
|
||||||
raise RuntimeError("Refusing to create an inheritance cycle")
|
|
||||||
cls._abc_registry.add(subclass)
|
|
||||||
ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
|
|
||||||
|
|
||||||
def _dump_registry(cls, file=None):
|
|
||||||
"""Debug helper to print the ABC registry."""
|
|
||||||
print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__)
|
|
||||||
print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter
|
|
||||||
for name in sorted(cls.__dict__.keys()):
|
|
||||||
if name.startswith("_abc_"):
|
|
||||||
value = getattr(cls, name)
|
|
||||||
print >> file, "%s: %r" % (name, value)
|
|
||||||
|
|
||||||
def __instancecheck__(cls, instance):
|
|
||||||
"""Override for isinstance(instance, cls)."""
|
|
||||||
# Inline the cache checking when it's simple.
|
|
||||||
subclass = getattr(instance, '__class__', None)
|
|
||||||
if subclass in cls._abc_cache:
|
|
||||||
return True
|
|
||||||
subtype = type(instance)
|
|
||||||
# Old-style instances
|
|
||||||
if subtype is _InstanceType:
|
|
||||||
subtype = subclass
|
|
||||||
if subtype is subclass or subclass is None:
|
|
||||||
if (cls._abc_negative_cache_version ==
|
|
||||||
ABCMeta._abc_invalidation_counter and
|
|
||||||
subtype in cls._abc_negative_cache):
|
|
||||||
return False
|
|
||||||
# Fall back to the subclass check.
|
|
||||||
return cls.__subclasscheck__(subtype)
|
|
||||||
return (cls.__subclasscheck__(subclass) or
|
|
||||||
cls.__subclasscheck__(subtype))
|
|
||||||
|
|
||||||
def __subclasscheck__(cls, subclass):
|
|
||||||
"""Override for issubclass(subclass, cls)."""
|
|
||||||
# Check cache
|
|
||||||
if subclass in cls._abc_cache:
|
|
||||||
return True
|
|
||||||
# Check negative cache; may have to invalidate
|
|
||||||
if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
|
|
||||||
# Invalidate the negative cache
|
|
||||||
cls._abc_negative_cache = set()
|
|
||||||
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
|
|
||||||
elif subclass in cls._abc_negative_cache:
|
|
||||||
return False
|
|
||||||
# Check the subclass hook
|
|
||||||
ok = cls.__subclasshook__(subclass)
|
|
||||||
if ok is not NotImplemented:
|
|
||||||
assert isinstance(ok, bool)
|
|
||||||
if ok:
|
|
||||||
cls._abc_cache.add(subclass)
|
|
||||||
else:
|
|
||||||
cls._abc_negative_cache.add(subclass)
|
|
||||||
return ok
|
|
||||||
# Check if it's a direct subclass
|
|
||||||
if cls in getattr(subclass, '__mro__', ()):
|
|
||||||
cls._abc_cache.add(subclass)
|
|
||||||
return True
|
|
||||||
# Check if it's a subclass of a registered class (recursive)
|
|
||||||
for rcls in cls._abc_registry:
|
|
||||||
if issubclass(subclass, rcls):
|
|
||||||
cls._abc_cache.add(subclass)
|
|
||||||
return True
|
|
||||||
# Check if it's a subclass of a subclass (recursive)
|
|
||||||
for scls in cls.__subclasses__():
|
|
||||||
if issubclass(subclass, scls):
|
|
||||||
cls._abc_cache.add(subclass)
|
|
||||||
return True
|
|
||||||
# No dice; update negative cache
|
|
||||||
cls._abc_negative_cache.add(subclass)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _hasattr(C, attr):
|
|
||||||
try:
|
|
||||||
return any(attr in B.__dict__ for B in C.__mro__)
|
|
||||||
except AttributeError:
|
|
||||||
# Old-style class
|
|
||||||
return hasattr(C, attr)
|
|
||||||
|
|
||||||
|
|
||||||
class Sized:
|
|
||||||
__metaclass__ = ABCMeta
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __len__(self):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def __subclasshook__(cls, C):
|
|
||||||
if cls is Sized:
|
|
||||||
if _hasattr(C, "__len__"):
|
|
||||||
return True
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
|
|
||||||
class Container:
|
|
||||||
__metaclass__ = ABCMeta
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __contains__(self, x):
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def __subclasshook__(cls, C):
|
|
||||||
if cls is Container:
|
|
||||||
if _hasattr(C, "__contains__"):
|
|
||||||
return True
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
|
|
||||||
class Iterable:
|
|
||||||
__metaclass__ = ABCMeta
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __iter__(self):
|
|
||||||
while False:
|
|
||||||
yield None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def __subclasshook__(cls, C):
|
|
||||||
if cls is Iterable:
|
|
||||||
if _hasattr(C, "__iter__"):
|
|
||||||
return True
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
Iterable.register(str)
|
|
||||||
|
|
||||||
|
|
||||||
class Set(Sized, Iterable, Container):
|
|
||||||
"""A set is a finite, iterable container.
|
|
||||||
|
|
||||||
This class provides concrete generic implementations of all
|
|
||||||
methods except for __contains__, __iter__ and __len__.
|
|
||||||
|
|
||||||
To override the comparisons (presumably for speed, as the
|
|
||||||
semantics are fixed), all you have to do is redefine __le__ and
|
|
||||||
then the other operations will automatically follow suit.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __le__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
return NotImplemented
|
|
||||||
if len(self) > len(other):
|
|
||||||
return False
|
|
||||||
for elem in self:
|
|
||||||
if elem not in other:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
return NotImplemented
|
|
||||||
return len(self) < len(other) and self.__le__(other)
|
|
||||||
|
|
||||||
def __gt__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
return NotImplemented
|
|
||||||
return other < self
|
|
||||||
|
|
||||||
def __ge__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
return NotImplemented
|
|
||||||
return other <= self
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
return NotImplemented
|
|
||||||
return len(self) == len(other) and self.__le__(other)
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not (self == other)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _from_iterable(cls, it):
|
|
||||||
'''Construct an instance of the class from any iterable input.
|
|
||||||
|
|
||||||
Must override this method if the class constructor signature
|
|
||||||
does not accept an iterable for an input.
|
|
||||||
'''
|
|
||||||
return cls(it)
|
|
||||||
|
|
||||||
def __and__(self, other):
|
|
||||||
if not isinstance(other, Iterable):
|
|
||||||
return NotImplemented
|
|
||||||
return self._from_iterable(value for value in other if value in self)
|
|
||||||
|
|
||||||
def isdisjoint(self, other):
|
|
||||||
for value in other:
|
|
||||||
if value in self:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __or__(self, other):
|
|
||||||
if not isinstance(other, Iterable):
|
|
||||||
return NotImplemented
|
|
||||||
chain = (e for s in (self, other) for e in s)
|
|
||||||
return self._from_iterable(chain)
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
if not isinstance(other, Iterable):
|
|
||||||
return NotImplemented
|
|
||||||
other = self._from_iterable(other)
|
|
||||||
return self._from_iterable(value for value in self
|
|
||||||
if value not in other)
|
|
||||||
|
|
||||||
def __xor__(self, other):
|
|
||||||
if not isinstance(other, Set):
|
|
||||||
if not isinstance(other, Iterable):
|
|
||||||
return NotImplemented
|
|
||||||
other = self._from_iterable(other)
|
|
||||||
return (self - other) | (other - self)
|
|
||||||
|
|
||||||
# Sets are not hashable by default, but subclasses can change this
|
|
||||||
__hash__ = None
|
|
||||||
|
|
||||||
def _hash(self):
|
|
||||||
"""Compute the hash value of a set.
|
|
||||||
|
|
||||||
Note that we don't define __hash__: not all sets are hashable.
|
|
||||||
But if you define a hashable set type, its __hash__ should
|
|
||||||
call this function.
|
|
||||||
|
|
||||||
This must be compatible __eq__.
|
|
||||||
|
|
||||||
All sets ought to compare equal if they contain the same
|
|
||||||
elements, regardless of how they are implemented, and
|
|
||||||
regardless of the order of the elements; so there's not much
|
|
||||||
freedom for __eq__ or __hash__. We match the algorithm used
|
|
||||||
by the built-in frozenset type.
|
|
||||||
"""
|
|
||||||
MAX = sys.maxint
|
|
||||||
MASK = 2 * MAX + 1
|
|
||||||
n = len(self)
|
|
||||||
h = 1927868237 * (n + 1)
|
|
||||||
h &= MASK
|
|
||||||
for x in self:
|
|
||||||
hx = hash(x)
|
|
||||||
h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
|
|
||||||
h &= MASK
|
|
||||||
h = h * 69069 + 907133923
|
|
||||||
h &= MASK
|
|
||||||
if h > MAX:
|
|
||||||
h -= MASK + 1
|
|
||||||
if h == -1:
|
|
||||||
h = 590923713
|
|
||||||
return h
|
|
||||||
|
|
||||||
Set.register(frozenset)
|
|
||||||
|
|
||||||
|
|
||||||
class MutableSet(Set):
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def add(self, value):
|
|
||||||
"""Add an element."""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def discard(self, value):
|
|
||||||
"""Remove an element. Do not raise an exception if absent."""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def remove(self, value):
|
|
||||||
"""Remove an element. If not a member, raise a KeyError."""
|
|
||||||
if value not in self:
|
|
||||||
raise KeyError(value)
|
|
||||||
self.discard(value)
|
|
||||||
|
|
||||||
def pop(self):
|
|
||||||
"""Return the popped value. Raise KeyError if empty."""
|
|
||||||
it = iter(self)
|
|
||||||
try:
|
|
||||||
value = next(it)
|
|
||||||
except StopIteration:
|
|
||||||
raise KeyError
|
|
||||||
self.discard(value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
"""This is slow (creates N new iterators!) but effective."""
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
self.pop()
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __ior__(self, it):
|
|
||||||
for value in it:
|
|
||||||
self.add(value)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __iand__(self, it):
|
|
||||||
for value in (self - it):
|
|
||||||
self.discard(value)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __ixor__(self, it):
|
|
||||||
if not isinstance(it, Set):
|
|
||||||
it = self._from_iterable(it)
|
|
||||||
for value in it:
|
|
||||||
if value in self:
|
|
||||||
self.discard(value)
|
|
||||||
else:
|
|
||||||
self.add(value)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __isub__(self, it):
|
|
||||||
for value in it:
|
|
||||||
self.discard(value)
|
|
||||||
return self
|
|
||||||
|
|
||||||
MutableSet.register(set)
|
|
||||||
|
|
||||||
|
|
||||||
class OrderedSet(MutableSet):
|
|
||||||
|
|
||||||
def __init__(self, iterable=None):
|
|
||||||
self.end = end = []
|
|
||||||
end += [None, end, end] # sentinel node for doubly linked list
|
|
||||||
self.map = {} # key --> [key, prev, next]
|
|
||||||
if iterable is not None:
|
|
||||||
self |= iterable
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.map)
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
return key in self.map
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return list(self)[key]
|
|
||||||
|
|
||||||
def add(self, key):
|
|
||||||
if key not in self.map:
|
|
||||||
end = self.end
|
|
||||||
curr = end[PREV]
|
|
||||||
curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
|
|
||||||
|
|
||||||
def discard(self, key):
|
|
||||||
if key in self.map:
|
|
||||||
key, prev, next = self.map.pop(key)
|
|
||||||
prev[NEXT] = next
|
|
||||||
next[PREV] = prev
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
end = self.end
|
|
||||||
curr = end[NEXT]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[KEY]
|
|
||||||
curr = curr[NEXT]
|
|
||||||
|
|
||||||
def __reversed__(self):
|
|
||||||
end = self.end
|
|
||||||
curr = end[PREV]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[KEY]
|
|
||||||
curr = curr[PREV]
|
|
||||||
|
|
||||||
def pop(self, last=True):
|
|
||||||
if not self:
|
|
||||||
raise KeyError('set is empty')
|
|
||||||
key = next(reversed(self)) if last else next(iter(self))
|
|
||||||
self.discard(key)
|
|
||||||
return key
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self:
|
|
||||||
return '%s()' % (self.__class__.__name__,)
|
|
||||||
return '%s(%r)' % (self.__class__.__name__, list(self))
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, OrderedSet):
|
|
||||||
return len(self) == len(other) and list(self) == list(other)
|
|
||||||
return set(self) == set(other)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if all([KEY, PREV, NEXT]):
|
|
||||||
self.clear() # remove circular references
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print(OrderedSet('abracadaba'))
|
|
||||||
print(OrderedSet('simsalabim'))
|
|
83
thirdparty/oset/pyoset.py
vendored
83
thirdparty/oset/pyoset.py
vendored
|
@ -1,83 +0,0 @@
|
||||||
#!/usr/bin/env python2
|
|
||||||
# -*- mode:python; tab-width: 2; coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""Partially backported python ABC classes"""
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
try:
|
|
||||||
from collections import MutableSet
|
|
||||||
except ImportError:
|
|
||||||
# Running in Python <= 2.5
|
|
||||||
from ._abc import MutableSet
|
|
||||||
|
|
||||||
|
|
||||||
KEY, PREV, NEXT = range(3)
|
|
||||||
|
|
||||||
|
|
||||||
class OrderedSet(MutableSet):
|
|
||||||
|
|
||||||
def __init__(self, iterable=None):
|
|
||||||
self.end = end = []
|
|
||||||
end += [None, end, end] # sentinel node for doubly linked list
|
|
||||||
self.map = {} # key --> [key, prev, next]
|
|
||||||
if iterable is not None:
|
|
||||||
self |= iterable
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.map)
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
return key in self.map
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return list(self)[key]
|
|
||||||
|
|
||||||
def add(self, key):
|
|
||||||
if key not in self.map:
|
|
||||||
end = self.end
|
|
||||||
curr = end[PREV]
|
|
||||||
curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
|
|
||||||
|
|
||||||
def discard(self, key):
|
|
||||||
if key in self.map:
|
|
||||||
key, prev, next = self.map.pop(key)
|
|
||||||
prev[NEXT] = next
|
|
||||||
next[PREV] = prev
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
end = self.end
|
|
||||||
curr = end[NEXT]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[KEY]
|
|
||||||
curr = curr[NEXT]
|
|
||||||
|
|
||||||
def __reversed__(self):
|
|
||||||
end = self.end
|
|
||||||
curr = end[PREV]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[KEY]
|
|
||||||
curr = curr[PREV]
|
|
||||||
|
|
||||||
def pop(self, last=True):
|
|
||||||
if not self:
|
|
||||||
raise KeyError('set is empty')
|
|
||||||
key = next(reversed(self)) if last else next(iter(self))
|
|
||||||
self.discard(key)
|
|
||||||
return key
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self:
|
|
||||||
return '%s()' % (self.__class__.__name__,)
|
|
||||||
return '%s(%r)' % (self.__class__.__name__, list(self))
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, OrderedSet):
|
|
||||||
return len(self) == len(other) and list(self) == list(other)
|
|
||||||
return set(self) == set(other)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if all([KEY, PREV, NEXT]):
|
|
||||||
self.clear() # remove circular references
|
|
||||||
|
|
||||||
oset = OrderedSet
|
|
Loading…
Reference in New Issue
Block a user