<commit_before>from __future__ import division

import json
import os
import re
import sys
from subprocess import Popen, PIPE
from math import log, ceil
from tempfile import TemporaryFile
from warnings import warn
from functools import wraps

try:
    import audioop
except ImportError:
    import pyaudioop as audioop

if sys.version_info >= (3, 0):
    basestring = str

FRAME_WIDTHS = {
    8: 1,
    16: 2,
    32: 4,
}
ARRAY_TYPES = {
    8: "b",
    16: "h",
    32: "i",
}
ARRAY_RANGES = {
    8: (-0x80, 0x7f),
    16: (-0x8000, 0x7fff),
    32: (-0x80000000, 0x7fffffff),
}

def get_frame_width(bit_depth):
    return FRAME_WIDTHS[bit_depth]

def get_array_type(bit_depth, signed=True):
    t = ARRAY_TYPES[bit_depth]
    if not signed:
        t = t.upper()
    return t

def get_min_max_value(bit_depth):
    return ARRAY_RANGES[bit_depth]

def _fd_or_path_or_tempfile(fd, mode='w+b', tempfile=True):
    close_fd = False
    if fd is None and tempfile:
        fd = TemporaryFile(mode=mode)
        close_fd = True

    if isinstance(fd, basestring):
        fd = open(fd, mode=mode)
        close_fd = True

    try:
        if isinstance(fd, os.PathLike):
            fd = open(fd, mode=mode)
            close_fd = True
    except AttributeError:
        # module os has no attribute PathLike, so we're on python < 3.6.
        # The protocol we're trying to support doesn't exist, so just pass.
        pass

    return fd, close_fd

def db_to_float(db, using_amplitude=True):
    """
    Converts the input db to a float, which represents the equivalent
    ratio in power.
    """
    db = float(db)
    if using_amplitude:
        return 10 ** (db / 20)
    else:  # using power
        return 10 ** (db / 10)

def ratio_to_db(ratio, val2=None, using_amplitude=True):
    """
    Converts the input float to db, which represents the equivalent
    to the ratio in power represented by the multiplier passed in.
    """
    ratio = float(ratio)

    # accept 2 values and use the ratio of val1 to val2
    if val2 is not None:
        ratio = ratio / val2

    # special case for multiply-by-zero (convert to silence)
    if ratio == 0:
        return -float('inf')

    if using_amplitude:
        return 20 * log(ratio, 10)
    else:  # using power
        return 10 * log(ratio, 10)

def register_pydub_effect(fn, name=None):
    """
    decorator for adding pydub effects to the AudioSegment objects.
    example use:
        @register_pydub_effect
        def normalize(audio_segment):
            ...
    or you can specify a name:
        @register_pydub_effect("normalize")
        def normalize_audio_segment(audio_segment):
            ...
    """
    if isinstance(fn, basestring):
        name = fn
        return lambda fn: register_pydub_effect(fn, name)

    if name is None:
        name = fn.__name__

    from .audio_segment import AudioSegment
    setattr(AudioSegment, name, fn)
    return fn

def make_chunks(audio_segment, chunk_length):
    """
    Breaks an AudioSegment into chunks that are <chunk_length> milliseconds
    long.
    if chunk_length is 50 then you'll get a list of 50 millisecond long audio
    segments back (except the last one, which can be shorter)
    """
    number_of_chunks = ceil(len(audio_segment) / float(chunk_length))
    return [audio_segment[i * chunk_length:(i + 1) * chunk_length]
            for i in range(int(number_of_chunks))]

def which(program):
    """
    Mimics behavior of UNIX which command.
    """
    # Add .exe program extension for windows support
    if os.name == "nt" and not program.endswith(".exe"):
        program += ".exe"

    envdir_list = [os.curdir] + os.environ["PATH"].split(os.pathsep)

    for envdir in envdir_list:
        program_path = os.path.join(envdir, program)
        if os.path.isfile(program_path) and os.access(program_path, os.X_OK):
            return program_path

def get_encoder_name():
    """
    Return enconder default application for system, either avconv or ffmpeg
    """
    if which("avconv"):
        return "avconv"
    elif which("ffmpeg"):
        return "ffmpeg"
    else:
        # should raise exception
        warn("Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work", RuntimeWarning)
        return "ffmpeg"

def get_player_name():
    """
    Return enconder default application for system, either avconv or ffmpeg
    """
    if which("avplay"):
        return "avplay"
    elif which("ffplay"):
        return "ffplay"
    else:
        # should raise exception
        warn("Couldn't find ffplay or avplay - defaulting to ffplay, but may not work", RuntimeWarning)
        return "ffplay"

def get_prober_name():
    """
    Return probe application, either avconv or ffmpeg
    """
    if which("avprobe"):
        return "avprobe"
    elif which("ffprobe"):
        return "ffprobe"
    else:
        # should raise exception
        warn("Couldn't find ffprobe or avprobe - defaulting to ffprobe, but may not work", RuntimeWarning)
        return "ffprobe"

def fsdecode(filename):
    """Wrapper for os.fsdecode which was introduced in python 3.2 ."""

    if sys.version_info >= (3, 2):
        PathLikeTypes = (basestring, bytes)
        if sys.version_info >= (3, 6):
            PathLikeTypes += (os.PathLike,)
        if isinstance(filename, PathLikeTypes):
            return os.fsdecode(filename)
    else:
        if isinstance(filename, bytes):
            return filename.decode(sys.getfilesystemencoding())
        if isinstance(filename, basestring):
            return filename

    raise TypeError("type {0} not accepted by fsdecode".format(type(filename)))

def get_extra_info(stderr):
    """
    avprobe sometimes gives more information on stderr than
    on the json output. The information has to be extracted
    from stderr of the format of:
    '    Stream #0:0: Audio: flac, 88200 Hz, stereo, s32 (24 bit)'
    or (macOS version):
    '    Stream #0:0: Audio: vorbis'
    '      44100 Hz, stereo, fltp, 320 kb/s'

    :type stderr: str
    :rtype: list of dict
    """
    extra_info = {}

    re_stream = r'(?P<space_start> +)Stream #0[:\.](?P<stream_id>([0-9]+))(?P<content_0>.+)\n?(?! *Stream)((?P<space_end> +)(?P<content_1>.+))?'
    for i in re.finditer(re_stream, stderr):
        if i.group('space_end') is not None and len(i.group('space_start')) <= len(
                i.group('space_end')):
            content_line = ','.join([i.group('content_0'), i.group('content_1')])
        else:
            content_line = i.group('content_0')
        tokens = [x.strip() for x in re.split('[:,]', content_line) if x]
        extra_info[int(i.group('stream_id'))] = tokens
    return extra_info

def mediainfo_json(filepath, read_ahead_limit=-1):
    """Return json dictionary with media info(codec, duration, size, bitrate...) from filepath
    """
    prober = get_prober_name()
    command_args = [
        "-v", "info",
        "-show_format",
        "-show_streams",
    ]
    try:
        command_args += [fsdecode(filepath)]
        stdin_parameter = None
        stdin_data = None
    except TypeError:
        if prober == 'ffprobe':
            command_args += ["-read_ahead_limit", str(read_ahead_limit),
                             "cache:pipe:0"]
        else:
            command_args += ["-"]
        stdin_parameter = PIPE
        file, close_file = _fd_or_path_or_tempfile(filepath, 'rb', tempfile=False)
        file.seek(0)
        stdin_data = file.read()
        if close_file:
            file.close()

    command = [prober, '-of', 'json'] + command_args
    res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE)
    output, stderr = res.communicate(input=stdin_data)
    output = output.decode("utf-8", 'ignore')
    stderr = stderr.decode("utf-8", 'ignore')

    info = json.loads(output)

    if not info:
        # If ffprobe didn't give any information, just return it
        # (for example, because the file doesn't exist)
        return info

    extra_info = get_extra_info(stderr)

    audio_streams = [x for x in info['streams'] if x['codec_type'] == 'audio']
    if len(audio_streams) == 0:
        return info

    # We just operate on the first audio stream in case there are more
    stream = audio_streams[0]

    def set_property(stream, prop, value):
        if prop not in stream or stream[prop] == 0:
            stream[prop] = value

    for token in extra_info[stream['index']]:
        m = re.match(r'([su]([0-9]{1,2})p?) \(([0-9]{1,2}) bit\)$', token)
        m2 = re.match(r'([su]([0-9]{1,2})p?)( \(default\))?$', token)
        if m:
            set_property(stream, 'sample_fmt', m.group(1))
            set_property(stream, 'bits_per_sample', int(m.group(2)))
            set_property(stream, 'bits_per_raw_sample', int(m.group(3)))
        elif m2:
            set_property(stream, 'sample_fmt', m2.group(1))
            set_property(stream, 'bits_per_sample', int(m2.group(2)))
            set_property(stream, 'bits_per_raw_sample', int(m2.group(2)))
        elif re.match(r'(flt)p?( \(default\))?$', token):
            set_property(stream, 'sample_fmt', token)
            set_property(stream, 'bits_per_sample', 32)
            set_property(stream, 'bits_per_raw_sample', 32)
        elif re.match(r'(dbl)p?( \(default\))?$', token):
            set_property(stream, 'sample_fmt', token)
            set_property(stream, 'bits_per_sample', 64)
            set_property(stream, 'bits_per_raw_sample', 64)
    return info

def mediainfo(filepath):
    """Return dictionary with media info(codec, duration, size, bitrate...) from filepath
    """

    prober = get_prober_name()
    command_args = [
        "-v", "quiet",
        "-show_format",
        "-show_streams",
        filepath
    ]

    command = [prober, '-of', 'old'] + command_args
    res = Popen(command, stdout=PIPE)
    output = res.communicate()[0].decode("utf-8")

    if res.returncode != 0:
        command = [prober] + command_args
        output = Popen(command, stdout=PIPE).communicate()[0].decode("utf-8")

    rgx = re.compile(r"(?:(?P<inner_dict>.*?):)?(?P<key>.*?)\=(?P<value>.*?)$")
    info = {}

    if sys.platform == 'win32':
        output = output.replace("\r", "")

    for line in output.split("\n"):
        # print(line)
        mobj = rgx.match(line)

        if mobj:
            # print(mobj.groups())
            inner_dict, key, value = mobj.groups()

            if inner_dict:
                try:
                    info[inner_dict]
                except KeyError:
                    info[inner_dict] = {}
                info[inner_dict][key] = value
            else:
                info[key] = value

    return info

def cache_codecs(function):
    cache = {}

    @wraps(function)
    def wrapper():
        try:
            return cache[0]
        except:
            cache[0] = function()
            return cache[0]

    return wrapper

@cache_codecs
def get_supported_codecs():
    encoder = get_encoder_name()
    command = [encoder, "-codecs"]
    res = Popen(command, stdout=PIPE, stderr=PIPE)
    output = res.communicate()[0].decode("utf-8")
    if res.returncode != 0:
        return []

    if sys.platform == 'win32':
        output = output.replace("\r", "")

    rgx = re.compile(r"^([D.][E.][AVS.][I.][L.][S.]) (\w*) +(.*)")
    decoders = set()
    encoders = set()
    for line in output.split('\n'):
        match = rgx.match(line.strip())
        if not match:
            continue
        flags, codec, name = match.groups()

        if flags[0] == 'D':
            decoders.add(codec)

        if flags[1] == 'E':
            encoders.add(codec)

    return (decoders, encoders)

def get_supported_decoders():
    return get_supported_codecs()[0]

def get_supported_encoders():
    return get_supported_codecs()[1]

def stereo_to_ms(audio_segment):
	'''
	Left-Right -> Mid-Side
	'''
	channel = audio_segment.split_to_mono()
	channel = [channel[0].overlay(channel[1]), channel[0].overlay(channel[1].invert_phase())]
	return AudioSegment.from_mono_audiosegments(channel[0], channel[1])

def ms_to_stereo(audio_segment):
	'''
	Mid-Side -> Left-Right
	'''
	channel = audio_segment.split_to_mono()
	channel = [channel[0].overlay(channel[1]) - 3, channel[0].overlay(channel[1].invert_phase()) - 3]
	return AudioSegment.from_mono_audiosegments(channel[0], channel[1])

<commit_msg>Fix for #604 (`json.loads()` on an empty string) (#652)<commit_after>from __future__ import division

import json
import os
import re
import sys
from subprocess import Popen, PIPE
from math import log, ceil
from tempfile import TemporaryFile
from warnings import warn
from functools import wraps

try:
    import audioop
except ImportError:
    import pyaudioop as audioop

if sys.version_info >= (3, 0):
    basestring = str

FRAME_WIDTHS = {
    8: 1,
    16: 2,
    32: 4,
}
ARRAY_TYPES = {
    8: "b",
    16: "h",
    32: "i",
}
ARRAY_RANGES = {
    8: (-0x80, 0x7f),
    16: (-0x8000, 0x7fff),
    32: (-0x80000000, 0x7fffffff),
}

def get_frame_width(bit_depth):
    return FRAME_WIDTHS[bit_depth]

def get_array_type(bit_depth, signed=True):
    t = ARRAY_TYPES[bit_depth]
    if not signed:
        t = t.upper()
    return t

def get_min_max_value(bit_depth):
    return ARRAY_RANGES[bit_depth]

def _fd_or_path_or_tempfile(fd, mode='w+b', tempfile=True):
    close_fd = False
    if fd is None and tempfile:
        fd = TemporaryFile(mode=mode)
        close_fd = True

    if isinstance(fd, basestring):
        fd = open(fd, mode=mode)
        close_fd = True

    try:
        if isinstance(fd, os.PathLike):
            fd = open(fd, mode=mode)
            close_fd = True
    except AttributeError:
        # module os has no attribute PathLike, so we're on python < 3.6.
        # The protocol we're trying to support doesn't exist, so just pass.
        pass

    return fd, close_fd

def db_to_float(db, using_amplitude=True):
    """
    Converts the input db to a float, which represents the equivalent
    ratio in power.
    """
    db = float(db)
    if using_amplitude:
        return 10 ** (db / 20)
    else:  # using power
        return 10 ** (db / 10)

def ratio_to_db(ratio, val2=None, using_amplitude=True):
    """
    Converts the input float to db, which represents the equivalent
    to the ratio in power represented by the multiplier passed in.
    """
    ratio = float(ratio)

    # accept 2 values and use the ratio of val1 to val2
    if val2 is not None:
        ratio = ratio / val2

    # special case for multiply-by-zero (convert to silence)
    if ratio == 0:
        return -float('inf')

    if using_amplitude:
        return 20 * log(ratio, 10)
    else:  # using power
        return 10 * log(ratio, 10)

def register_pydub_effect(fn, name=None):
    """
    decorator for adding pydub effects to the AudioSegment objects.
    example use:
        @register_pydub_effect
        def normalize(audio_segment):
            ...
    or you can specify a name:
        @register_pydub_effect("normalize")
        def normalize_audio_segment(audio_segment):
            ...
    """
    if isinstance(fn, basestring):
        name = fn
        return lambda fn: register_pydub_effect(fn, name)

    if name is None:
        name = fn.__name__

    from .audio_segment import AudioSegment
    setattr(AudioSegment, name, fn)
    return fn

def make_chunks(audio_segment, chunk_length):
    """
    Breaks an AudioSegment into chunks that are <chunk_length> milliseconds
    long.
    if chunk_length is 50 then you'll get a list of 50 millisecond long audio
    segments back (except the last one, which can be shorter)
    """
    number_of_chunks = ceil(len(audio_segment) / float(chunk_length))
    return [audio_segment[i * chunk_length:(i + 1) * chunk_length]
            for i in range(int(number_of_chunks))]

def which(program):
    """
    Mimics behavior of UNIX which command.
    """
    # Add .exe program extension for windows support
    if os.name == "nt" and not program.endswith(".exe"):
        program += ".exe"

    envdir_list = [os.curdir] + os.environ["PATH"].split(os.pathsep)

    for envdir in envdir_list:
        program_path = os.path.join(envdir, program)
        if os.path.isfile(program_path) and os.access(program_path, os.X_OK):
            return program_path

def get_encoder_name():
    """
    Return enconder default application for system, either avconv or ffmpeg
    """
    if which("avconv"):
        return "avconv"
    elif which("ffmpeg"):
        return "ffmpeg"
    else:
        # should raise exception
        warn("Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work", RuntimeWarning)
        return "ffmpeg"

def get_player_name():
    """
    Return enconder default application for system, either avconv or ffmpeg
    """
    if which("avplay"):
        return "avplay"
    elif which("ffplay"):
        return "ffplay"
    else:
        # should raise exception
        warn("Couldn't find ffplay or avplay - defaulting to ffplay, but may not work", RuntimeWarning)
        return "ffplay"

def get_prober_name():
    """
    Return probe application, either avconv or ffmpeg
    """
    if which("avprobe"):
        return "avprobe"
    elif which("ffprobe"):
        return "ffprobe"
    else:
        # should raise exception
        warn("Couldn't find ffprobe or avprobe - defaulting to ffprobe, but may not work", RuntimeWarning)
        return "ffprobe"

def fsdecode(filename):
    """Wrapper for os.fsdecode which was introduced in python 3.2 ."""

    if sys.version_info >= (3, 2):
        PathLikeTypes = (basestring, bytes)
        if sys.version_info >= (3, 6):
            PathLikeTypes += (os.PathLike,)
        if isinstance(filename, PathLikeTypes):
            return os.fsdecode(filename)
    else:
        if isinstance(filename, bytes):
            return filename.decode(sys.getfilesystemencoding())
        if isinstance(filename, basestring):
            return filename

    raise TypeError("type {0} not accepted by fsdecode".format(type(filename)))

def get_extra_info(stderr):
    """
    avprobe sometimes gives more information on stderr than
    on the json output. The information has to be extracted
    from stderr of the format of:
    '    Stream #0:0: Audio: flac, 88200 Hz, stereo, s32 (24 bit)'
    or (macOS version):
    '    Stream #0:0: Audio: vorbis'
    '      44100 Hz, stereo, fltp, 320 kb/s'

    :type stderr: str
    :rtype: list of dict
    """
    extra_info = {}

    re_stream = r'(?P<space_start> +)Stream #0[:\.](?P<stream_id>([0-9]+))(?P<content_0>.+)\n?(?! *Stream)((?P<space_end> +)(?P<content_1>.+))?'
    for i in re.finditer(re_stream, stderr):
        if i.group('space_end') is not None and len(i.group('space_start')) <= len(
                i.group('space_end')):
            content_line = ','.join([i.group('content_0'), i.group('content_1')])
        else:
            content_line = i.group('content_0')
        tokens = [x.strip() for x in re.split('[:,]', content_line) if x]
        extra_info[int(i.group('stream_id'))] = tokens
    return extra_info

def mediainfo_json(filepath, read_ahead_limit=-1):
    """Return json dictionary with media info(codec, duration, size, bitrate...) from filepath
    """
    prober = get_prober_name()
    command_args = [
        "-v", "info",
        "-show_format",
        "-show_streams",
    ]
    try:
        command_args += [fsdecode(filepath)]
        stdin_parameter = None
        stdin_data = None
    except TypeError:
        if prober == 'ffprobe':
            command_args += ["-read_ahead_limit", str(read_ahead_limit),
                             "cache:pipe:0"]
        else:
            command_args += ["-"]
        stdin_parameter = PIPE
        file, close_file = _fd_or_path_or_tempfile(filepath, 'rb', tempfile=False)
        file.seek(0)
        stdin_data = file.read()
        if close_file:
            file.close()

    command = [prober, '-of', 'json'] + command_args
    res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE)
    output, stderr = res.communicate(input=stdin_data)
    output = output.decode("utf-8", 'ignore')
    stderr = stderr.decode("utf-8", 'ignore')

    try:
        info = json.loads(output)
    except  json.decoder.JSONDecodeError:
        # If ffprobe didn't give any information, just return it
        # (for example, because the file doesn't exist)
        return None
    if not info:
        return info

    extra_info = get_extra_info(stderr)

    audio_streams = [x for x in info['streams'] if x['codec_type'] == 'audio']
    if len(audio_streams) == 0:
        return info

    # We just operate on the first audio stream in case there are more
    stream = audio_streams[0]

    def set_property(stream, prop, value):
        if prop not in stream or stream[prop] == 0:
            stream[prop] = value

    for token in extra_info[stream['index']]:
        m = re.match(r'([su]([0-9]{1,2})p?) \(([0-9]{1,2}) bit\)$', token)
        m2 = re.match(r'([su]([0-9]{1,2})p?)( \(default\))?$', token)
        if m:
            set_property(stream, 'sample_fmt', m.group(1))
            set_property(stream, 'bits_per_sample', int(m.group(2)))
            set_property(stream, 'bits_per_raw_sample', int(m.group(3)))
        elif m2:
            set_property(stream, 'sample_fmt', m2.group(1))
            set_property(stream, 'bits_per_sample', int(m2.group(2)))
            set_property(stream, 'bits_per_raw_sample', int(m2.group(2)))
        elif re.match(r'(flt)p?( \(default\))?$', token):
            set_property(stream, 'sample_fmt', token)
            set_property(stream, 'bits_per_sample', 32)
            set_property(stream, 'bits_per_raw_sample', 32)
        elif re.match(r'(dbl)p?( \(default\))?$', token):
            set_property(stream, 'sample_fmt', token)
            set_property(stream, 'bits_per_sample', 64)
            set_property(stream, 'bits_per_raw_sample', 64)
    return info

def mediainfo(filepath):
    """Return dictionary with media info(codec, duration, size, bitrate...) from filepath
    """

    prober = get_prober_name()
    command_args = [
        "-v", "quiet",
        "-show_format",
        "-show_streams",
        filepath
    ]

    command = [prober, '-of', 'old'] + command_args
    res = Popen(command, stdout=PIPE)
    output = res.communicate()[0].decode("utf-8")

    if res.returncode != 0:
        command = [prober] + command_args
        output = Popen(command, stdout=PIPE).communicate()[0].decode("utf-8")

    rgx = re.compile(r"(?:(?P<inner_dict>.*?):)?(?P<key>.*?)\=(?P<value>.*?)$")
    info = {}

    if sys.platform == 'win32':
        output = output.replace("\r", "")

    for line in output.split("\n"):
        # print(line)
        mobj = rgx.match(line)

        if mobj:
            # print(mobj.groups())
            inner_dict, key, value = mobj.groups()

            if inner_dict:
                try:
                    info[inner_dict]
                except KeyError:
                    info[inner_dict] = {}
                info[inner_dict][key] = value
            else:
                info[key] = value

    return info

def cache_codecs(function):
    cache = {}

    @wraps(function)
    def wrapper():
        try:
            return cache[0]
        except:
            cache[0] = function()
            return cache[0]

    return wrapper

@cache_codecs
def get_supported_codecs():
    encoder = get_encoder_name()
    command = [encoder, "-codecs"]
    res = Popen(command, stdout=PIPE, stderr=PIPE)
    output = res.communicate()[0].decode("utf-8")
    if res.returncode != 0:
        return []

    if sys.platform == 'win32':
        output = output.replace("\r", "")

    rgx = re.compile(r"^([D.][E.][AVS.][I.][L.][S.]) (\w*) +(.*)")
    decoders = set()
    encoders = set()
    for line in output.split('\n'):
        match = rgx.match(line.strip())
        if not match:
            continue
        flags, codec, name = match.groups()

        if flags[0] == 'D':
            decoders.add(codec)

        if flags[1] == 'E':
            encoders.add(codec)

    return (decoders, encoders)

def get_supported_decoders():
    return get_supported_codecs()[0]

def get_supported_encoders():
    return get_supported_codecs()[1]

def stereo_to_ms(audio_segment):
	'''
	Left-Right -> Mid-Side
	'''
	channel = audio_segment.split_to_mono()
	channel = [channel[0].overlay(channel[1]), channel[0].overlay(channel[1].invert_phase())]
	return AudioSegment.from_mono_audiosegments(channel[0], channel[1])

def ms_to_stereo(audio_segment):
	'''
	Mid-Side -> Left-Right
	'''
	channel = audio_segment.split_to_mono()
	channel = [channel[0].overlay(channel[1]) - 3, channel[0].overlay(channel[1].invert_phase()) - 3]
	return AudioSegment.from_mono_audiosegments(channel[0], channel[1])

<|endoftext|>


<commit_before>from .utils import EqualityComparableUsingAttributeDictionary
from .filters import Filter, TermFilter, TermsFilter, ANDFilter, NotFilter

class FacetFactory(EqualityComparableUsingAttributeDictionary):

    def __init__(self):
        self.facets = []

    def add_term_facet(self, *args, **kwargs):
        """Add a term factory facet"""
        self.facets.append(TermFacet(*args, **kwargs))

    def add_date_facet(self, *args, **kwargs):
        """Add a date factory facet"""
        self.facets.append(DateHistogramFacet(*args, **kwargs))

    def add_geo_facet(self, *args, **kwargs):
        """Add a geo factory facet"""
        self.facets.append(GeoDistanceFacet(*args, **kwargs))

    def add(self, facet):
        """Add a term factory"""
        self.facets.append(facet)

    def reset(self):
        """Reset the facets"""
        self.facets = []

    def serialize(self):
        res = {}
        for facet in self.facets:
            res.update(facet.serialize())
        return res

class Facet(EqualityComparableUsingAttributeDictionary):

    def __init__(self, name, scope=None, nested=None, is_global=None,
                 facet_filter=None, **kwargs):
        self.name = name
        self.scope = scope
        self.nested = nested
        self.is_global = is_global
        self.facet_filter = facet_filter

    def serialize(self):
        data = {self._internal_name: self._serialize()}
        if self.scope is not None:
            data["scope"] = self.scope
        if self.nested is not None:
            data["nested"] = self.nested
        if self.is_global:
            data['global'] = self.is_global
        if self.facet_filter:
            data['facet_filter'] = self.facet_filter.serialize()
        return {self.name: data}

    def _serialize(self):
        raise NotImplementedError

    @property
    def _internal_name(self):
        raise NotImplementedError

# TODO: remove these
FacetFilter = Filter
TermFacetFilter = TermFilter
TermsFacetFilter = TermsFilter
ANDFacetFilter = ANDFilter
NotFacetFilter = NotFilter

class QueryFacet(Facet):

    _internal_name = "query"

    def __init__(self, name, query, **kwargs):
        super(QueryFacet, self).__init__(name, **kwargs)
        self.query = query

    def _serialize(self):
        return self.query.serialize()

class FilterFacet(Facet):

    _internal_name = "filter"

    def __init__(self, name, filter, **kwargs):
        super(FilterFacet, self).__init__(name, **kwargs)
        self.filter = filter

    def _serialize(self):
        return self.filter.serialize()

class HistogramFacet(Facet):

    _internal_name = "histogram"

    def __init__(self, name, field=None, interval=None, time_interval=None,
                 key_field=None, value_field=None, key_script=None,
                 value_script=None, params=None, **kwargs):
        super(HistogramFacet, self).__init__(name, **kwargs)
        self.field = field
        self.interval = interval
        self.time_interval = time_interval
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _add_interval(self, data):
        if self.interval:
            data['interval'] = self.interval
        elif self.time_interval:
            data['time_interval'] = self.time_interval
        else:
            raise RuntimeError("Invalid field: interval or time_interval required")

    def _serialize(self):
        data = {}
        if self.field:
            data['field'] = self.field
            self._add_interval(data)
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
            self._add_interval(data)
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
            if self.interval:
                data['interval'] = self.interval
            elif self.time_interval:
                data['time_interval'] = self.time_interval
        return data

class DateHistogramFacet(Facet):

    _internal_name = "date_histogram"

    def __init__(self, name, field=None, interval=None, zone=None, key_field=None,
                 value_field=None, value_script=None, params=None, **kwargs):
        super(DateHistogramFacet, self).__init__(name, **kwargs)
        self.field = field
        self.interval = interval
        self.zone = zone
        self.key_field = key_field
        self.value_field = value_field
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if self.interval:
            data['interval'] = self.interval
            if self.zone:
                data['zone'] = self.zone
        else:
            raise RuntimeError("interval required")
        if self.field:
            data['field'] = self.field
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            elif self.value_script:
                data['value_script'] = self.value_script
                if self.params:
                    data['params'] = self.params
            else:
                raise RuntimeError("Invalid key_field: value_field or value_script required")
        return data

class RangeFacet(Facet):

    _internal_name = "range"

    def __init__(self, name, field=None, ranges=None, key_field=None, value_field=None,
                 key_script=None, value_script=None, params=None, **kwargs):
        super(RangeFacet, self).__init__(name, **kwargs)
        self.field = field
        self.ranges = ranges or []
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if not self.ranges:
            raise RuntimeError("Invalid ranges")
        data['ranges'] = self.ranges
        if self.field:
            data['field'] = self.field
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
        return data

class GeoDistanceFacet(RangeFacet):

    _internal_name = "geo_distance"

    def __init__(self, name, field, pin, ranges=None, value_field=None,
                 value_script=None, distance_unit=None, distance_type=None,
                 params=None, **kwargs):
        super(RangeFacet, self).__init__(name, **kwargs)
        self.field = field
        self.pin = pin
        self.distance_unit = distance_unit
        self.distance_type = distance_type
        self.ranges = ranges or []
        self.value_field = value_field
        self.value_script = value_script
        self.params = params
        self.DISTANCE_TYPES = ['arc', 'plane']
        self.UNITS = ['km', 'mi', 'miles']

    def _serialize(self):
        if not self.ranges:
            raise RuntimeError("Invalid ranges")
        data = {}
        data['ranges'] = self.ranges
        data[self.field] = self.pin
        if self.distance_type:
            if self.distance_type not in self.DISTANCE_TYPES:
                raise RuntimeError("Invalid distance_type: must be one of %s" %
                    self.DISTANCE_TYPES)
            data['distance_type'] = self.distance_type
        if self.distance_unit:
            if self.distance_unit not in self.UNITS:
                raise RuntimeError("Invalid unit: must be one of %s" %
                    self.DISTANCE_TYPES)
            data['unit'] = self.distance_unit
        if self.value_field:
            data['value_field'] = self.value_field
        elif self.value_script:
            data['value_script'] = self.value_script
            if self.params:
                data['params'] = self.params
        return data

class StatisticalFacet(Facet):

    _internal_name = "statistical"

    def __init__(self, name, field=None, script=None, params=None, **kwargs):
        super(StatisticalFacet, self).__init__(name, **kwargs)
        self.field = field
        self.script = script
        self.params = params

    def _serialize(self):
        data = {}
        if self.field:
            data['field'] = self.field
        elif self.script:
            data['script'] = self.script
            if self.params:
                data['params'] = self.params
        return data

class TermFacet(Facet):

    _internal_name = "terms"

    def __init__(self, field=None, fields=None, name=None, size=10, order=None,
                 exclude=None, regex=None, regex_flags="DOTALL", script=None,
                 all_terms=None, **kwargs):
        super(TermFacet, self).__init__(name or field, **kwargs)
        self.field = field
        self.fields = fields
        self.size = size
        self.order = order
        self.exclude = exclude or []
        self.regex = regex
        self.regex_flags = regex_flags
        self.script = script
        self.all_terms = all_terms

    def _serialize(self):
        if not self.fields or not self.field or not self.script:
            raise RuntimeError("Field, Fields or Script is required:%s" % self.order)

        data = {}
        if self.fields:
            data['fields'] = self.fields
        elif self.field:
            data['field'] = self.field

        if self.script:
            data['script'] = self.script
        if self.size is not None:
            data['size'] = self.size
        if self.order:
            if self.order not in ['count', 'term', 'reverse_count', 'reverse_term']:
                raise RuntimeError("Invalid order value:%s" % self.order)
            data['order'] = self.order
        if self.exclude:
            data['exclude'] = self.exclude
        if (self.fields or self.field) and self.regex:
            data['regex'] = self.regex
            if self.regex_flags:
                data['regex_flags'] = self.regex_flags
        if self.all_terms:
            data['all_terms'] = self.all_terms
        return data

class TermStatsFacet(Facet):

    _internal_name = "terms_stats"

    def __init__(self, name, size=10, order=None, key_field=None, value_field=None,
                 key_script=None, value_script=None, params=None, **kwargs):
        super(TermStatsFacet, self).__init__(name, **kwargs)
        self.size = size
        self.ORDER_VALUES = ['term', 'reverse_term', 'count', 'reverse_count',
                             'total', 'reverse_total', 'min', 'reverse_min',
                             'max', 'reverse_max', 'mean', 'reverse_mean']
        self.order = order if order is not None else self.ORDER_VALUES[0]
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if self.size is not None:
            data['size'] = self.size
        if self.order:
            if self.order not in self.ORDER_VALUES:
                raise RuntimeError("Invalid order value:%s" % self.order)
            data['order'] = self.order
        if self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
        return data

class FacetQueryWrap(EqualityComparableUsingAttributeDictionary):

    def __init__(self, wrap_object, **kwargs):
        """Base Object for every Filter Object"""
        self.wrap_object = wrap_object

    def serialize(self):
        return {"query": self.wrap_object.serialize()}
<commit_msg>Logic fix for TermFacet _serialize check<commit_after>from .utils import EqualityComparableUsingAttributeDictionary
from .filters import Filter, TermFilter, TermsFilter, ANDFilter, NotFilter

class FacetFactory(EqualityComparableUsingAttributeDictionary):

    def __init__(self):
        self.facets = []

    def add_term_facet(self, *args, **kwargs):
        """Add a term factory facet"""
        self.facets.append(TermFacet(*args, **kwargs))

    def add_date_facet(self, *args, **kwargs):
        """Add a date factory facet"""
        self.facets.append(DateHistogramFacet(*args, **kwargs))

    def add_geo_facet(self, *args, **kwargs):
        """Add a geo factory facet"""
        self.facets.append(GeoDistanceFacet(*args, **kwargs))

    def add(self, facet):
        """Add a term factory"""
        self.facets.append(facet)

    def reset(self):
        """Reset the facets"""
        self.facets = []

    def serialize(self):
        res = {}
        for facet in self.facets:
            res.update(facet.serialize())
        return res

class Facet(EqualityComparableUsingAttributeDictionary):

    def __init__(self, name, scope=None, nested=None, is_global=None,
                 facet_filter=None, **kwargs):
        self.name = name
        self.scope = scope
        self.nested = nested
        self.is_global = is_global
        self.facet_filter = facet_filter

    def serialize(self):
        data = {self._internal_name: self._serialize()}
        if self.scope is not None:
            data["scope"] = self.scope
        if self.nested is not None:
            data["nested"] = self.nested
        if self.is_global:
            data['global'] = self.is_global
        if self.facet_filter:
            data['facet_filter'] = self.facet_filter.serialize()
        return {self.name: data}

    def _serialize(self):
        raise NotImplementedError

    @property
    def _internal_name(self):
        raise NotImplementedError

# TODO: remove these
FacetFilter = Filter
TermFacetFilter = TermFilter
TermsFacetFilter = TermsFilter
ANDFacetFilter = ANDFilter
NotFacetFilter = NotFilter

class QueryFacet(Facet):

    _internal_name = "query"

    def __init__(self, name, query, **kwargs):
        super(QueryFacet, self).__init__(name, **kwargs)
        self.query = query

    def _serialize(self):
        return self.query.serialize()

class FilterFacet(Facet):

    _internal_name = "filter"

    def __init__(self, name, filter, **kwargs):
        super(FilterFacet, self).__init__(name, **kwargs)
        self.filter = filter

    def _serialize(self):
        return self.filter.serialize()

class HistogramFacet(Facet):

    _internal_name = "histogram"

    def __init__(self, name, field=None, interval=None, time_interval=None,
                 key_field=None, value_field=None, key_script=None,
                 value_script=None, params=None, **kwargs):
        super(HistogramFacet, self).__init__(name, **kwargs)
        self.field = field
        self.interval = interval
        self.time_interval = time_interval
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _add_interval(self, data):
        if self.interval:
            data['interval'] = self.interval
        elif self.time_interval:
            data['time_interval'] = self.time_interval
        else:
            raise RuntimeError("Invalid field: interval or time_interval required")

    def _serialize(self):
        data = {}
        if self.field:
            data['field'] = self.field
            self._add_interval(data)
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
            self._add_interval(data)
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
            if self.interval:
                data['interval'] = self.interval
            elif self.time_interval:
                data['time_interval'] = self.time_interval
        return data

class DateHistogramFacet(Facet):

    _internal_name = "date_histogram"

    def __init__(self, name, field=None, interval=None, zone=None, key_field=None,
                 value_field=None, value_script=None, params=None, **kwargs):
        super(DateHistogramFacet, self).__init__(name, **kwargs)
        self.field = field
        self.interval = interval
        self.zone = zone
        self.key_field = key_field
        self.value_field = value_field
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if self.interval:
            data['interval'] = self.interval
            if self.zone:
                data['zone'] = self.zone
        else:
            raise RuntimeError("interval required")
        if self.field:
            data['field'] = self.field
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            elif self.value_script:
                data['value_script'] = self.value_script
                if self.params:
                    data['params'] = self.params
            else:
                raise RuntimeError("Invalid key_field: value_field or value_script required")
        return data

class RangeFacet(Facet):

    _internal_name = "range"

    def __init__(self, name, field=None, ranges=None, key_field=None, value_field=None,
                 key_script=None, value_script=None, params=None, **kwargs):
        super(RangeFacet, self).__init__(name, **kwargs)
        self.field = field
        self.ranges = ranges or []
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if not self.ranges:
            raise RuntimeError("Invalid ranges")
        data['ranges'] = self.ranges
        if self.field:
            data['field'] = self.field
        elif self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
        return data

class GeoDistanceFacet(RangeFacet):

    _internal_name = "geo_distance"

    def __init__(self, name, field, pin, ranges=None, value_field=None,
                 value_script=None, distance_unit=None, distance_type=None,
                 params=None, **kwargs):
        super(RangeFacet, self).__init__(name, **kwargs)
        self.field = field
        self.pin = pin
        self.distance_unit = distance_unit
        self.distance_type = distance_type
        self.ranges = ranges or []
        self.value_field = value_field
        self.value_script = value_script
        self.params = params
        self.DISTANCE_TYPES = ['arc', 'plane']
        self.UNITS = ['km', 'mi', 'miles']

    def _serialize(self):
        if not self.ranges:
            raise RuntimeError("Invalid ranges")
        data = {}
        data['ranges'] = self.ranges
        data[self.field] = self.pin
        if self.distance_type:
            if self.distance_type not in self.DISTANCE_TYPES:
                raise RuntimeError("Invalid distance_type: must be one of %s" %
                    self.DISTANCE_TYPES)
            data['distance_type'] = self.distance_type
        if self.distance_unit:
            if self.distance_unit not in self.UNITS:
                raise RuntimeError("Invalid unit: must be one of %s" %
                    self.DISTANCE_TYPES)
            data['unit'] = self.distance_unit
        if self.value_field:
            data['value_field'] = self.value_field
        elif self.value_script:
            data['value_script'] = self.value_script
            if self.params:
                data['params'] = self.params
        return data

class StatisticalFacet(Facet):

    _internal_name = "statistical"

    def __init__(self, name, field=None, script=None, params=None, **kwargs):
        super(StatisticalFacet, self).__init__(name, **kwargs)
        self.field = field
        self.script = script
        self.params = params

    def _serialize(self):
        data = {}
        if self.field:
            data['field'] = self.field
        elif self.script:
            data['script'] = self.script
            if self.params:
                data['params'] = self.params
        return data

class TermFacet(Facet):

    _internal_name = "terms"

    def __init__(self, field=None, fields=None, name=None, size=10, order=None,
                 exclude=None, regex=None, regex_flags="DOTALL", script=None,
                 all_terms=None, **kwargs):
        super(TermFacet, self).__init__(name or field, **kwargs)
        self.field = field
        self.fields = fields
        self.size = size
        self.order = order
        self.exclude = exclude or []
        self.regex = regex
        self.regex_flags = regex_flags
        self.script = script
        self.all_terms = all_terms

    def _serialize(self):
        if not self.fields and not self.field and not self.script:
            raise RuntimeError("Field, Fields or Script is required:%s" % self.order)

        data = {}
        if self.fields:
            data['fields'] = self.fields
        elif self.field:
            data['field'] = self.field

        if self.script:
            data['script'] = self.script
        if self.size is not None:
            data['size'] = self.size
        if self.order:
            if self.order not in ['count', 'term', 'reverse_count', 'reverse_term']:
                raise RuntimeError("Invalid order value:%s" % self.order)
            data['order'] = self.order
        if self.exclude:
            data['exclude'] = self.exclude
        if (self.fields or self.field) and self.regex:
            data['regex'] = self.regex
            if self.regex_flags:
                data['regex_flags'] = self.regex_flags
        if self.all_terms:
            data['all_terms'] = self.all_terms
        return data

class TermStatsFacet(Facet):

    _internal_name = "terms_stats"

    def __init__(self, name, size=10, order=None, key_field=None, value_field=None,
                 key_script=None, value_script=None, params=None, **kwargs):
        super(TermStatsFacet, self).__init__(name, **kwargs)
        self.size = size
        self.ORDER_VALUES = ['term', 'reverse_term', 'count', 'reverse_count',
                             'total', 'reverse_total', 'min', 'reverse_min',
                             'max', 'reverse_max', 'mean', 'reverse_mean']
        self.order = order if order is not None else self.ORDER_VALUES[0]
        self.key_field = key_field
        self.value_field = value_field
        self.key_script = key_script
        self.value_script = value_script
        self.params = params

    def _serialize(self):
        data = {}
        if self.size is not None:
            data['size'] = self.size
        if self.order:
            if self.order not in self.ORDER_VALUES:
                raise RuntimeError("Invalid order value:%s" % self.order)
            data['order'] = self.order
        if self.key_field:
            data['key_field'] = self.key_field
            if self.value_field:
                data['value_field'] = self.value_field
            else:
                raise RuntimeError("Invalid key_field: value_field required")
        elif self.key_script:
            data['key_script'] = self.key_script
            if self.value_script:
                data['value_script'] = self.value_script
            else:
                raise RuntimeError("Invalid key_script: value_script required")
            if self.params:
                data['params'] = self.params
        return data

class FacetQueryWrap(EqualityComparableUsingAttributeDictionary):

    def __init__(self, wrap_object, **kwargs):
        """Base Object for every Filter Object"""
        self.wrap_object = wrap_object

    def serialize(self):
        return {"query": self.wrap_object.serialize()}
<|endoftext|>


<commit_before>import numpy as np
import scipy as sp
from scipy import sparse
from math import isinf, isnan

def is_directed(G):
    r"""
    Returns a bool:  True if the graph is directed and false if not
    The Weight matrix has to be sparse (For now)
    Can also be used to check if a matrix is symetrical
    """

    is_dir = (G.W - G.W.transpose()).sum() != 0
    return is_dir

def estimate_lmax(G):
    r"""
    TODO write doc
    """
    try:
        # MAT: lmax=eigs(G.L,1,'lm',opts)
        lmax = sparse.linalg.eigs(G.L, k=1, tol=5e-3, ncv=10)[0]
        # On robustness purposes, increasing the error by 1 percent
        lmax *= 1.01
    except ValueError:
        print('GSP_ESTIMATE_LMAX: Cannot use default method')
        lmax = max(G.d)
    return lmax

def check_weights(W):
    r"""
    Check a weight matrix
    Returns an array of bools:
        has_inf_val
        has_nan_value
        is_not_square
        diag_is_not_zero
    """
    has_inf_val = False
    diag_is_not_zero = False
    is_not_square = False
    has_nan_value = False
    if isinf(W.sum()):
        print("GSP_TEST_WEIGHTS: There is an inifinite \
              value in the weight matrix")
        has_inf_val = True
    if abs(W.diagonal()).sum():
        print("GSP_TEST_WEIGHTS: The main diagonal of \
              the weight matrix is not 0!")
        diag_is_not_zero = True
    if W.get_shape()[0] != W.get_shape()[1]:
        print("GSP_TEST_WEIGHTS: The weight matrix is \
              not square!")
        is_not_square = True
    if isnan(W.sum()):
        print("GSP_TEST_WEIGHTS: There is an inifinite \
              value in the weight matrix")
        has_nan_value = True

    return [has_inf_val, has_nan_value, is_not_square, diag_is_not_zero]

def create_laplacian(G):
    if G.lap_type == 'combinatorial':
        L = sparse.lil_matrix(G.W.sum().diagonal() - G.W)
    if G.lap_type == 'normalized':
        D = sparse.lil_matrix(G.W.sum().diagonal() ** (-0.5))
        L = sparse.lil_matrix(np.matlib.identity(G.N)) - D * G.W * D
    if G.lap_type == 'none':
        L = sparse.lil_matrix(0)
    else:
        raise AttributeError('Unknown laplacian type!')
    return L

def check_connectivity(G, **kwargs):
    A = G.W
    # Removing the diagonal
    A -= A.diagonal()
    if G.directed:
        return _check_connectivity_directed(A, kwargs)
    else:
        return _check_connectivity_undirected(A, kwargs)
    pass

def _check_connectivity_directed(A, **kwargs):
    is_connected = (A.W <= 0).all()
    for c in sp.shape(A.W)[0]:
        c_is_connected = (c == 0).all()
        if c_is_connected:
            break
    for r in sp.shape(A.W)[1]:
        r_is_connected = (c == 0).all()
        if r_is_connected:
            break
    # TODO check axises
    in_conn = (A.sum(axis=1)>0).nonzeros()
    out_conn = (A.sum(axis=2)>0).nonzeros()

    if c_is_connected and r_is_connected:
        return True, in_conn, out_conn

def _check_connectivity_undirected(A, **kwargs):
    is_connected = (A.W <= 0).all()
    for c in sp.shape(A.W)[0]:
        c_is_connected = (c == 0).all()
        if c_is_connected:
            break
    # TODO check axises
    in_conn = (A.sum(axis=1)>0).nonzeros()
    out_conn = in_conn
    if c_is_connected and r_is_connected:
        return True, in_conn, out_conn

def distanz(x, y=None):
    r"""
    paramters:
        - x: matrix with col vectors
        - y: matrix with col vectors
    """
    if y is None:
        y = x

    rx, cx = x.shape()
    ry, cy = y.shape()

    # Size verification
    if rx != ry:
        raise("The sizes of x and y do not fit")
    xx = (x**x).sum()
    yy = (y**y).sum()
    xy = np.transpose(x)*y
    d = abs(sp.kron(sp.ones((1, cy)), xx) + sp.kron(sp.ones((cx, 1)), yy) - 2*xy)
<commit_msg>fix laplacian<commit_after>import numpy as np
import scipy as sp
from scipy import sparse
from math import isinf, isnan

def is_directed(G):
    r"""
    Returns a bool:  True if the graph is directed and false if not
    The Weight matrix has to be sparse (For now)
    Can also be used to check if a matrix is symetrical
    """

    is_dir = (G.W - G.W.transpose()).sum() != 0
    return is_dir

def estimate_lmax(G):
    r"""
    TODO write doc
    """
    try:
        # MAT: lmax=eigs(G.L,1,'lm',opts)
        lmax = sparse.linalg.eigs(G.L, k=1, tol=5e-3, ncv=10)[0]
        # On robustness purposes, increasing the error by 1 percent
        lmax *= 1.01
    except ValueError:
        print('GSP_ESTIMATE_LMAX: Cannot use default method')
        lmax = max(G.d)
    return lmax

def check_weights(W):
    r"""
    Check a weight matrix
    Returns an array of bools:
        has_inf_val
        has_nan_value
        is_not_square
        diag_is_not_zero
    """
    has_inf_val = False
    diag_is_not_zero = False
    is_not_square = False
    has_nan_value = False
    if isinf(W.sum()):
        print("GSP_TEST_WEIGHTS: There is an inifinite \
              value in the weight matrix")
        has_inf_val = True
    if abs(W.diagonal()).sum():
        print("GSP_TEST_WEIGHTS: The main diagonal of \
              the weight matrix is not 0!")
        diag_is_not_zero = True
    if W.get_shape()[0] != W.get_shape()[1]:
        print("GSP_TEST_WEIGHTS: The weight matrix is \
              not square!")
        is_not_square = True
    if isnan(W.sum()):
        print("GSP_TEST_WEIGHTS: There is an inifinite \
              value in the weight matrix")
        has_nan_value = True

    return [has_inf_val, has_nan_value, is_not_square, diag_is_not_zero]

def create_laplacian(G):
    if sp.shape(G.W) == (1,1):
        return sparse.lil_matrix(0)
    else:
        if G.lap_type == 'combinatorial':
            L = sparse.lil_matrix(G.W.sum().diagonal() - G.W)
        if G.lap_type == 'normalized':
            D = sparse.lil_matrix(G.W.sum().diagonal() ** (-0.5))
            L = sparse.lil_matrix(np.matlib.identity(G.N)) - D * G.W * D
        if G.lap_type == 'none':
            L = sparse.lil_matrix(0)
        else:
            raise AttributeError('Unknown laplacian type!')
        return L

def check_connectivity(G, **kwargs):
    A = G.W
    # Removing the diagonal
    A -= A.diagonal()
    if G.directed:
        return _check_connectivity_directed(A, kwargs)
    else:
        return _check_connectivity_undirected(A, kwargs)
    pass

def _check_connectivity_directed(A, **kwargs):
    is_connected = (A.W <= 0).all()
    for c in sp.shape(A.W)[0]:
        c_is_connected = (c == 0).all()
        if c_is_connected:
            break
    for r in sp.shape(A.W)[1]:
        r_is_connected = (c == 0).all()
        if r_is_connected:
            break
    # TODO check axises
    in_conn = (A.sum(axis=1)>0).nonzeros()
    out_conn = (A.sum(axis=2)>0).nonzeros()

    if c_is_connected and r_is_connected:
        return True, in_conn, out_conn

def _check_connectivity_undirected(A, **kwargs):
    is_connected = (A.W <= 0).all()
    for c in sp.shape(A.W)[0]:
        c_is_connected = (c == 0).all()
        if c_is_connected:
            break
    # TODO check axises
    in_conn = (A.sum(axis=1)>0).nonzeros()
    out_conn = in_conn
    if c_is_connected and r_is_connected:
        return True, in_conn, out_conn

def distanz(x, y=None):
    r"""
    paramters:
        - x: matrix with col vectors
        - y: matrix with col vectors
    """
    if y is None:
        y = x

    rx, cx = x.shape()
    ry, cy = y.shape()

    # Size verification
    if rx != ry:
        raise("The sizes of x and y do not fit")
    xx = (x**x).sum()
    yy = (y**y).sum()
    xy = np.transpose(x)*y
    d = abs(sp.kron(sp.ones((1, cy)), xx) + sp.kron(sp.ones((cx, 1)), yy) - 2*xy)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright 2014 Pierre de Buyl
#
# This file is part of pyh5md
#
# pyh5md is free software and is licensed under the modified BSD license (see
# LICENSE file).

import numpy as np
import h5py

VL_STR = h5py.special_dtype(vlen=str)

def populate_H5MD_data(g, name, shape, dtype, chunks=None):
    """Creates a step,time,value H5MD data group."""
    g.step = g.create_dataset('step', shape=(0,), dtype=np.int32, maxshape=(None,))
    g.time = g.create_dataset('time', shape=(0,), dtype=np.float64, maxshape=(None,))
    g.value = g.create_dataset('value', shape=(0,)+shape, dtype=dtype, maxshape=(None,)+shape, chunks=chunks)

class TimeData(h5py.Group):
    """Represents time-dependent data within a H5MD file."""
    def __init__(self, parent, name, shape=None, dtype=None, data=None, chunks=None, unit=None, time_unit = None):
        """Create a new TimeData object."""
        if name in parent.keys():
            self._id = h5py.h5g.open(parent.id, name)
            self.step = self['step']
            self.time = self['time']
            self.value = self['value']
        else:
            if data is not None:
                if shape is not None or isinstance(dtype, np.dtype):
                    raise Exception('Overspecification')
                else:
                    self._id = h5py.h5g.create(parent.id, name)
                    populate_H5MD_data(self, name, data.shape, data.dtype, chunks=chunks)
            else:
                self._id = h5py.h5g.create(parent.id, name)
                populate_H5MD_data(self, name, shape, dtype, chunks=chunks)
            if unit is not None:
                self['value'].attrs.create('unit',data=unit,dtype=VL_STR)
            if time_unit is not None:
                self['time'].attrs.create('unit',data=time_unit,dtype=VL_STR)

    def append(self, data, step, time):
        """Appends a time slice to the data group."""
        s = self['step']
        t = self['time']
        v = self['value']
        if not isinstance(data, np.ndarray):
            data = np.array(data, ndmin=0, dtype=v.dtype)
        assert s.shape[0]==t.shape[0] and t.shape[0]==v.shape[0]
        assert data.shape==v.shape[1:]
        idx = v.shape[0]
        v.resize(idx+1,axis=0)
        v[-1] = data
        s.resize(idx+1, axis=0)
        s[-1] = step
        t.resize(idx+1, axis=0)
        t[-1] = time

class FixedData(h5py.Dataset):
    """Represents time-independent data within a H5MD file."""
    def __init__(self, parent, name, shape=None, dtype=None, data=None, unit=None):
        if name not in parent.keys():
            parent.create_dataset(name, shape, dtype, data)
        oid = h5py.h5o.open(parent.id, name)
        h5py.Dataset.__init__(self, oid)
        if unit is not None:
            self.attrs.create('unit',data=unit,dtype=VL_STR)
<commit_msg>Fix copyright years.<commit_after># -*- coding: utf-8 -*-
# Copyright 2012-2014 Pierre de Buyl
#
# This file is part of pyh5md
#
# pyh5md is free software and is licensed under the modified BSD license (see
# LICENSE file).

import numpy as np
import h5py

VL_STR = h5py.special_dtype(vlen=str)

def populate_H5MD_data(g, name, shape, dtype, chunks=None):
    """Creates a step,time,value H5MD data group."""
    g.step = g.create_dataset('step', shape=(0,), dtype=np.int32, maxshape=(None,))
    g.time = g.create_dataset('time', shape=(0,), dtype=np.float64, maxshape=(None,))
    g.value = g.create_dataset('value', shape=(0,)+shape, dtype=dtype, maxshape=(None,)+shape, chunks=chunks)

class TimeData(h5py.Group):
    """Represents time-dependent data within a H5MD file."""
    def __init__(self, parent, name, shape=None, dtype=None, data=None, chunks=None, unit=None, time_unit = None):
        """Create a new TimeData object."""
        if name in parent.keys():
            self._id = h5py.h5g.open(parent.id, name)
            self.step = self['step']
            self.time = self['time']
            self.value = self['value']
        else:
            if data is not None:
                if shape is not None or isinstance(dtype, np.dtype):
                    raise Exception('Overspecification')
                else:
                    self._id = h5py.h5g.create(parent.id, name)
                    populate_H5MD_data(self, name, data.shape, data.dtype, chunks=chunks)
            else:
                self._id = h5py.h5g.create(parent.id, name)
                populate_H5MD_data(self, name, shape, dtype, chunks=chunks)
            if unit is not None:
                self['value'].attrs.create('unit',data=unit,dtype=VL_STR)
            if time_unit is not None:
                self['time'].attrs.create('unit',data=time_unit,dtype=VL_STR)

    def append(self, data, step, time):
        """Appends a time slice to the data group."""
        s = self['step']
        t = self['time']
        v = self['value']
        if not isinstance(data, np.ndarray):
            data = np.array(data, ndmin=0, dtype=v.dtype)
        assert s.shape[0]==t.shape[0] and t.shape[0]==v.shape[0]
        assert data.shape==v.shape[1:]
        idx = v.shape[0]
        v.resize(idx+1,axis=0)
        v[-1] = data
        s.resize(idx+1, axis=0)
        s[-1] = step
        t.resize(idx+1, axis=0)
        t[-1] = time

class FixedData(h5py.Dataset):
    """Represents time-independent data within a H5MD file."""
    def __init__(self, parent, name, shape=None, dtype=None, data=None, unit=None):
        if name not in parent.keys():
            parent.create_dataset(name, shape, dtype, data)
        oid = h5py.h5o.open(parent.id, name)
        h5py.Dataset.__init__(self, oid)
        if unit is not None:
            self.attrs.create('unit',data=unit,dtype=VL_STR)
<|endoftext|>


<commit_before>#import win32traceutil

import win32con
import sys
import os
from ctypes import *
import time

import _mshtml

import win32con

from ctypes import *
from ctypes.wintypes import *
from comtypes import IUnknown
from comtypes.automation import IDispatch, VARIANT
from comtypes.client import wrap, GetModule
from comtypes.client.dynamic import Dispatch

#from win32com.client import *
#cast = gencache.GetModuleForProgID('htmlfile')

if not hasattr(sys, 'frozen'):
    GetModule('atl.dll')
    GetModule('shdocvw.dll')

kernel32 = windll.kernel32
user32 = windll.user32
atl = windll.atl                  # If this fails, you need atl.dll

import win32con
from ctypes import *
from comtypes import IUnknown
from comtypes.automation import VARIANT
from comtypes.client import GetEvents
from comtypes.gen import SHDocVw
from comtypes.gen import MSHTML

kernel32 = windll.kernel32
user32 = windll.user32

WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)

class WNDCLASS(Structure):
    _fields_ = [('style', c_uint),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', c_int),
                ('cbWndExtra', c_int),
                ('hInstance', c_int),
                ('hIcon', c_int),
                ('hCursor', c_int),
                ('hbrBackground', c_int),
                ('lpszMenuName', c_char_p),
                ('lpszClassName', c_char_p)]

class RECT(Structure):
    _fields_ = [('left', c_long),
                ('top', c_long),
                ('right', c_long),
                ('bottom', c_long)]

class PAINTSTRUCT(Structure):
    _fields_ = [('hdc', c_int),
                ('fErase', c_int),
                ('rcPaint', RECT),
                ('fRestore', c_int),
                ('fIncUpdate', c_int),
                ('rgbReserved', c_char * 32)]

class POINT(Structure):
    _fields_ = [('x', c_long),
                ('y', c_long)]

class MSG(Structure):
    _fields_ = [('hwnd', c_int),
                ('message', c_uint),
                ('wParam', c_int),
                ('lParam', c_int),
                ('time', c_int),
                ('pt', POINT)]

def ErrorIfZero(handle):
    if handle == 0:
        raise WinError
    else:
        return handle

def _createDiv(doc):
    div = doc.createElement('div')
    print div
    style = div.style
    print style
    #style2 = style.QueryInterface(MSHTML.IHTMLStyle2)
    #style3 = style.QueryInterface(MSHTML.IHTMLStyle3)
    style.position = 'absolute'
    print "pos", style.position
    style.top = 0
    print "top", style.top
    sys.stdout.flush()
    print "left before", style.left
    style.left = 0
    print "left", style.left
    style.overflow = 'scroll'
    print "overflow", style.overflow
    style.overflowX = 'hidden'
    print "overflowX", style.overflowX
    style.width = 300
    print "width", style.width
    style.height = 100
    print "height", style.height
    style.scrollbarBaseColor = '#3366CC'
    style.borderBottom = '2px solid black'
    style.scrollbarHighlightColor = '#99CCFF'
    style.scrollbarArrowColor = 'white'
    div.innerHTML = 'Hello'
    return div

#b = Dispatch('InternetExplorer.Application')
#b.Navigate('about:
Hello
')
#b.Visible = 1
#doc1 = cast.IHTMLDocument2(b.Document)
#header = doc1.all.item('header')
#frm = doc1.all.item('frm')
#frm2 = doc1.frames('frm')
#doc2 = cast.IHTMLDocument2(frm2.document)
#div = doc2.createElement('div')
#cast.DispHTMLBody(doc2.body).appendChild(div)

#popup = cast.DispHTMLWindow2(doc1.parentWindow).createPopup()
#doc3 = cast.IHTMLDocument2(popup.document)
#body = cast.DispHTMLBody(doc3.body)
#div = _createDiv()

class EventSink(object):
    # some DWebBrowserEvents
    def OnVisible(self, this, *args):
        print "OnVisible", args

    def BeforeNavigate(self, this, *args):
        print "BeforeNavigate", args

    def NavigateComplete(self, this, *args):
        print "NavigateComplete", this, args
        return

    # some DWebBrowserEvents2
    def BeforeNavigate2(self, this, *args):
        print "BeforeNavigate2", args

    def NavigateComplete2(self, this, *args):
        print "NavigateComplete2", args

    def DocumentComplete(self, this, *args):
        print "DocumentComplete", args
        if self.workaround_ignore_first_doc_complete == False:
            # ignore first about:blank.  *sigh*...
            # TODO: work out how to parse *args byref VARIANT
            # in order to get at the URI.
            self.workaround_ignore_first_doc_complete = True
            return

        self._loaded()

    def NewWindow2(self, this, *args):
        print "NewWindow2", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

    def NewWindow3(self, this, *args):
        print "NewWindow3", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

def addWindowEventListener(self, event_name, cb):
    #print self, event_name, cb
    if cb not in self._callbacks:
        self.connect("browser-event", cb)
        self._callbacks.append(cb)
    return self.addWindowEventListener(event_name, True)

def addXMLHttpRequestEventListener(element, event_name, cb):
    if not hasattr(element, "_callbacks"):
        element._callbacks = []
    if cb not in element._callbacks:
        element.connect("browser-event", cb)
        element._callbacks.append(cb)
    return element.addEventListener(event_name)

def addEventListener(element, event_name, cb):
    if not hasattr(element, "_callbacks"):
        element._callbacks = []
    if cb not in element._callbacks:
        element.connect("browser-event", cb)
        element._callbacks.append(cb)
    return element.addEventListener(event_name, True)

class EventHandler:
    def __init__(self, pBrowser):
        self._pBrowser = pBrowser
        self._listeners = {}

    def _event_redirect(self, name, *args):
        callbacks = self.handler._listeners.get(name, [])
        for fn in callbacks:
            fn(*args)

    def addEventListener(self, name, fn):
        if not self._listeners.has_key(name):
            self._listeners[name] = []
        self._listeners[name].append(fn)

window_event_names = \
    ['onerror',
    'onscroll',
    'onload',
    'onhelp',
    'onresize',
    'onfocus',
    'onblur',
    'onunload',
    'onbeforeunload']

html_element_event_names = \
    ['ondragenter',
    'onrowsinserted',
    'onbeforecut',
    'onscroll',
    'oncopy',
    'onbeforepaste',
    'ondragover',
    'oncellchange',
    'ondragleave',
    'onresize',
    'onfocus',
    'ondrag',
    'onblur',
    'ondrop',
    'onrowsdelete',
    'onpropertychange',
    'onbeforeeditfocus',
    'onbeforecopy',
    'onpaste',
    'oncontextmenu',
    'ondragend',
    'onlosecapture',
    'oncut',
    'onreadystatechange']

fn_txt = """\
def %s(self, *args):
    return self._event_redirect('%s', *args)
%s['%s'] = %s
"""
el_methods = {}
for fname in html_element_event_names:
    fn_name = 'html_element_'+fname
    e = fn_txt % (fn_name, fname, 'el_methods', fname, fn_name)
    print e
    exec e in globals()

print el_methods

window_methods = {}
for fname in window_event_names:
    fn_name = 'window_'+fname
    e = fn_txt % (fn_name, fname, 'window_methods', fname, fn_name)
    print e
    exec e in globals()

print window_methods

ElementEventHandler = type('ElementEventHandler', (EventHandler,), el_methods)
WindowEventHandler = type('WindowtEventHandler', (EventHandler,), window_methods)

class Browser(EventSink):
    def __init__(self, application, appdir):
        EventSink.__init__(self)
        self.platform = 'mshtml'
        self.application = application
        self.appdir = appdir
        self.already_initialised = False
        self.workaround_ignore_first_doc_complete = False
        self.window_handler = None
        self.node_handlers = {}

        CreateWindowEx = windll.user32.CreateWindowExA
        CreateWindowEx.argtypes = [c_int, c_char_p, c_char_p, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int]
        CreateWindowEx.restype = ErrorIfZero

        # Create an instance of IE via AtlAxWin.
        atl.AtlAxWinInit()
        hInstance = kernel32.GetModuleHandleA(None)

        self.hwnd = CreateWindowEx(0,
                              "AtlAxWin",
                              "about:blank",
                              win32con.WS_OVERLAPPEDWINDOW |
                              win32con.WS_VISIBLE |
                              win32con.WS_HSCROLL | win32con.WS_VSCROLL,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.NULL,
                              win32con.NULL,
                              hInstance,
                              win32con.NULL)

        # Get the IWebBrowser2 interface for the IE control.
        self.pBrowserUnk = POINTER(IUnknown)()
        atl.AtlAxGetControl(self.hwnd, byref(self.pBrowserUnk))
        # the wrap call querys for the default interface
        self.pBrowser = wrap(self.pBrowserUnk)
        self.pBrowser.RegisterAsBrowser = True
        self.pBrowser.AddRef()

        self.conn = GetEvents(self.pBrowser, sink=self,
                        interface=SHDocVw.DWebBrowserEvents2)

    def _alert(self, txt):
        self.get_prompt_svc().alert(None, "Alert", txt)

    def load_app(self):

        uri = self.application
        if uri.find(":") == -1:
            # assume file
            uri = 'file://'+os.path.abspath(uri)

        print "load_app", uri

        self.application = uri
        v = byref(VARIANT())
        self.pBrowser.Navigate(uri, v, v, v, v)

        # Show Window
        cw = c_int(self.hwnd)
        windll.user32.ShowWindow(cw, c_int(win32con.SW_SHOWNORMAL))
        windll.user32.UpdateWindow(cw)

    def getGdomDocument(self):
        return Dispatch(self.pBrowser.Document)

    def getGdomWindow(self):
        return Dispatch(self.pBrowser.Document.window)

    def _addXMLHttpRequestEventListener(self, node, event_name, event_fn):

        return None
        listener = xpcom.server.WrapObject(ContentInvoker(node, event_fn),
                                            interfaces.nsIDOMEventListener)
        print event_name, listener
        node.addEventListener(event_name, listener, False)
        return listener

    def addEventListener(self, node, event_name, event_fn):

        if not self.node_handlers.has_key(node):
            nh  = ElementEventHandler(self)
            self.node_handlers[node] = nh
            conn = GetEvents(node, sink=nh, interface=MSHTML.HTMLElementEvents2)
        else:
            nh = self.node_handlers[node]

        nh.addEventListener(event_name, event_fn)

        return nh # hmmm...

    def mash_attrib(self, attrib_name):
        return attrib_name

    def _addWindowEventListener(self, event_name, event_fn):

        if self.window_handler is None:
            self.window_handler = WindowEventHandler(self)
            self.window_conn = GetEvents(self.pBrowser.Document.window,
                                        sink=self.window_handler,
                                    interface=MSHTML.HTMLWindowEvents2)
        self.window_handler.addEventListener(event_name, event_fn)
        return event_name # hmmm...

    def getXmlHttpRequest(self):
        xml_svc_cls = components.classes[ \
            "@mozilla.org/xmlextras/xmlhttprequest;1"]
        return xml_svc_cls.createInstance(interfaces.nsIXMLHttpRequest)

    def getUri(self):
        return self.application

    def _loaded(self):

        print "loaded"

        if self.already_initialised:
            return
        self.already_initialised = True

        from __pyjamas__ import pygwt_processMetas, set_main_frame
        #from __pyjamas__ import set_gtk_module
        set_main_frame(self)
        #set_gtk_module(gtk)

        (pth, app) = os.path.split(self.application)
        if self.appdir:
            pth = os.path.abspath(self.appdir)
        sys.path.append(pth)

def MainWin(one_event):

    # Pump Messages
    msg = MSG()
    pMsg = pointer(msg)
    NULL = c_int(win32con.NULL)

    while windll.user32.GetMessageA( pMsg, NULL, 0, 0) != 0:

        windll.user32.TranslateMessage(pMsg)
        windll.user32.DispatchMessageA(pMsg)

        #print msg.message, msg.wParam, msg.lParam
        #if msg.message == 161: # win32con.WM_DESTROY:
        #    windll.user32.PostQuitMessage(0)

        if one_event:
            break

    return msg.wParam

class ContentInvoker:

    def __init__(self, node, event_fn):
        self._node = node
        self._event_fn = event_fn

    def handleEvent(self, event):
        self._event_fn(self._node, event, False)

global wv
wv = None

def is_loaded():
    return wv.already_initialised

def run(one_event=False, block=True):
    MainWin(one_event) # TODO: ignore block arg for now

def setup(application, appdir=None, width=800, height=600):

    global wv
    wv = Browser(application, appdir)

    wv.load_app()

    while 1:
        if is_loaded():
            return
        run(one_event=True)

<commit_msg>whoops, must be object base<commit_after>#import win32traceutil

import win32con
import sys
import os
from ctypes import *
import time

import _mshtml

import win32con

from ctypes import *
from ctypes.wintypes import *
from comtypes import IUnknown
from comtypes.automation import IDispatch, VARIANT
from comtypes.client import wrap, GetModule
from comtypes.client.dynamic import Dispatch

#from win32com.client import *
#cast = gencache.GetModuleForProgID('htmlfile')

if not hasattr(sys, 'frozen'):
    GetModule('atl.dll')
    GetModule('shdocvw.dll')

kernel32 = windll.kernel32
user32 = windll.user32
atl = windll.atl                  # If this fails, you need atl.dll

import win32con
from ctypes import *
from comtypes import IUnknown
from comtypes.automation import VARIANT
from comtypes.client import GetEvents
from comtypes.gen import SHDocVw
from comtypes.gen import MSHTML

kernel32 = windll.kernel32
user32 = windll.user32

WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)

class WNDCLASS(Structure):
    _fields_ = [('style', c_uint),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', c_int),
                ('cbWndExtra', c_int),
                ('hInstance', c_int),
                ('hIcon', c_int),
                ('hCursor', c_int),
                ('hbrBackground', c_int),
                ('lpszMenuName', c_char_p),
                ('lpszClassName', c_char_p)]

class RECT(Structure):
    _fields_ = [('left', c_long),
                ('top', c_long),
                ('right', c_long),
                ('bottom', c_long)]

class PAINTSTRUCT(Structure):
    _fields_ = [('hdc', c_int),
                ('fErase', c_int),
                ('rcPaint', RECT),
                ('fRestore', c_int),
                ('fIncUpdate', c_int),
                ('rgbReserved', c_char * 32)]

class POINT(Structure):
    _fields_ = [('x', c_long),
                ('y', c_long)]

class MSG(Structure):
    _fields_ = [('hwnd', c_int),
                ('message', c_uint),
                ('wParam', c_int),
                ('lParam', c_int),
                ('time', c_int),
                ('pt', POINT)]

def ErrorIfZero(handle):
    if handle == 0:
        raise WinError
    else:
        return handle

def _createDiv(doc):
    div = doc.createElement('div')
    print div
    style = div.style
    print style
    #style2 = style.QueryInterface(MSHTML.IHTMLStyle2)
    #style3 = style.QueryInterface(MSHTML.IHTMLStyle3)
    style.position = 'absolute'
    print "pos", style.position
    style.top = 0
    print "top", style.top
    sys.stdout.flush()
    print "left before", style.left
    style.left = 0
    print "left", style.left
    style.overflow = 'scroll'
    print "overflow", style.overflow
    style.overflowX = 'hidden'
    print "overflowX", style.overflowX
    style.width = 300
    print "width", style.width
    style.height = 100
    print "height", style.height
    style.scrollbarBaseColor = '#3366CC'
    style.borderBottom = '2px solid black'
    style.scrollbarHighlightColor = '#99CCFF'
    style.scrollbarArrowColor = 'white'
    div.innerHTML = 'Hello'
    return div

#b = Dispatch('InternetExplorer.Application')
#b.Navigate('about:
Hello
')
#b.Visible = 1
#doc1 = cast.IHTMLDocument2(b.Document)
#header = doc1.all.item('header')
#frm = doc1.all.item('frm')
#frm2 = doc1.frames('frm')
#doc2 = cast.IHTMLDocument2(frm2.document)
#div = doc2.createElement('div')
#cast.DispHTMLBody(doc2.body).appendChild(div)

#popup = cast.DispHTMLWindow2(doc1.parentWindow).createPopup()
#doc3 = cast.IHTMLDocument2(popup.document)
#body = cast.DispHTMLBody(doc3.body)
#div = _createDiv()

class EventSink(object):
    # some DWebBrowserEvents
    def OnVisible(self, this, *args):
        print "OnVisible", args

    def BeforeNavigate(self, this, *args):
        print "BeforeNavigate", args

    def NavigateComplete(self, this, *args):
        print "NavigateComplete", this, args
        return

    # some DWebBrowserEvents2
    def BeforeNavigate2(self, this, *args):
        print "BeforeNavigate2", args

    def NavigateComplete2(self, this, *args):
        print "NavigateComplete2", args

    def DocumentComplete(self, this, *args):
        print "DocumentComplete", args
        if self.workaround_ignore_first_doc_complete == False:
            # ignore first about:blank.  *sigh*...
            # TODO: work out how to parse *args byref VARIANT
            # in order to get at the URI.
            self.workaround_ignore_first_doc_complete = True
            return

        self._loaded()

    def NewWindow2(self, this, *args):
        print "NewWindow2", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

    def NewWindow3(self, this, *args):
        print "NewWindow3", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

def addWindowEventListener(self, event_name, cb):
    #print self, event_name, cb
    if cb not in self._callbacks:
        self.connect("browser-event", cb)
        self._callbacks.append(cb)
    return self.addWindowEventListener(event_name, True)

def addXMLHttpRequestEventListener(element, event_name, cb):
    if not hasattr(element, "_callbacks"):
        element._callbacks = []
    if cb not in element._callbacks:
        element.connect("browser-event", cb)
        element._callbacks.append(cb)
    return element.addEventListener(event_name)

def addEventListener(element, event_name, cb):
    if not hasattr(element, "_callbacks"):
        element._callbacks = []
    if cb not in element._callbacks:
        element.connect("browser-event", cb)
        element._callbacks.append(cb)
    return element.addEventListener(event_name, True)

class EventHandler(object):
    def __init__(self, pBrowser):
        self._pBrowser = pBrowser
        self._listeners = {}

    def _event_redirect(self, name, *args):
        callbacks = self.handler._listeners.get(name, [])
        for fn in callbacks:
            fn(*args)

    def addEventListener(self, name, fn):
        if not self._listeners.has_key(name):
            self._listeners[name] = []
        self._listeners[name].append(fn)

window_event_names = \
    ['onerror',
    'onscroll',
    'onload',
    'onhelp',
    'onresize',
    'onfocus',
    'onblur',
    'onunload',
    'onbeforeunload']

html_element_event_names = \
    ['ondragenter',
    'onrowsinserted',
    'onbeforecut',
    'onscroll',
    'oncopy',
    'onbeforepaste',
    'ondragover',
    'oncellchange',
    'ondragleave',
    'onresize',
    'onfocus',
    'ondrag',
    'onblur',
    'ondrop',
    'onrowsdelete',
    'onpropertychange',
    'onbeforeeditfocus',
    'onbeforecopy',
    'onpaste',
    'oncontextmenu',
    'ondragend',
    'onlosecapture',
    'oncut',
    'onreadystatechange']

fn_txt = """\
def %s(self, *args):
    return self._event_redirect('%s', *args)
%s['%s'] = %s
"""
el_methods = {}
for fname in html_element_event_names:
    fn_name = 'html_element_'+fname
    e = fn_txt % (fn_name, fname, 'el_methods', fname, fn_name)
    exec e in globals()

print el_methods

window_methods = {}
for fname in window_event_names:
    fn_name = 'window_'+fname
    e = fn_txt % (fn_name, fname, 'window_methods', fname, fn_name)
    exec e in globals()

print window_methods

ElementEventHandler = type('ElementEventHandler', (EventHandler,), el_methods)
WindowEventHandler = type('WindowtEventHandler', (EventHandler,), window_methods)

class Browser(EventSink):
    def __init__(self, application, appdir):
        EventSink.__init__(self)
        self.platform = 'mshtml'
        self.application = application
        self.appdir = appdir
        self.already_initialised = False
        self.workaround_ignore_first_doc_complete = False
        self.window_handler = None
        self.node_handlers = {}

        CreateWindowEx = windll.user32.CreateWindowExA
        CreateWindowEx.argtypes = [c_int, c_char_p, c_char_p, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int]
        CreateWindowEx.restype = ErrorIfZero

        # Create an instance of IE via AtlAxWin.
        atl.AtlAxWinInit()
        hInstance = kernel32.GetModuleHandleA(None)

        self.hwnd = CreateWindowEx(0,
                              "AtlAxWin",
                              "about:blank",
                              win32con.WS_OVERLAPPEDWINDOW |
                              win32con.WS_VISIBLE |
                              win32con.WS_HSCROLL | win32con.WS_VSCROLL,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.NULL,
                              win32con.NULL,
                              hInstance,
                              win32con.NULL)

        # Get the IWebBrowser2 interface for the IE control.
        self.pBrowserUnk = POINTER(IUnknown)()
        atl.AtlAxGetControl(self.hwnd, byref(self.pBrowserUnk))
        # the wrap call querys for the default interface
        self.pBrowser = wrap(self.pBrowserUnk)
        self.pBrowser.RegisterAsBrowser = True
        self.pBrowser.AddRef()

        self.conn = GetEvents(self.pBrowser, sink=self,
                        interface=SHDocVw.DWebBrowserEvents2)

    def _alert(self, txt):
        self.get_prompt_svc().alert(None, "Alert", txt)

    def load_app(self):

        uri = self.application
        if uri.find(":") == -1:
            # assume file
            uri = 'file://'+os.path.abspath(uri)

        print "load_app", uri

        self.application = uri
        v = byref(VARIANT())
        self.pBrowser.Navigate(uri, v, v, v, v)

        # Show Window
        cw = c_int(self.hwnd)
        windll.user32.ShowWindow(cw, c_int(win32con.SW_SHOWNORMAL))
        windll.user32.UpdateWindow(cw)

    def getGdomDocument(self):
        return Dispatch(self.pBrowser.Document)

    def getGdomWindow(self):
        return Dispatch(self.pBrowser.Document.window)

    def _addXMLHttpRequestEventListener(self, node, event_name, event_fn):

        return None
        listener = xpcom.server.WrapObject(ContentInvoker(node, event_fn),
                                            interfaces.nsIDOMEventListener)
        print event_name, listener
        node.addEventListener(event_name, listener, False)
        return listener

    def addEventListener(self, node, event_name, event_fn):

        if not self.node_handlers.has_key(node):
            nh  = ElementEventHandler(self)
            self.node_handlers[node] = nh
            conn = GetEvents(node, sink=nh, interface=MSHTML.HTMLElementEvents2)
        else:
            nh = self.node_handlers[node]

        nh.addEventListener(event_name, event_fn)

        return nh # hmmm...

    def mash_attrib(self, attrib_name):
        return attrib_name

    def _addWindowEventListener(self, event_name, event_fn):

        if self.window_handler is None:
            self.window_handler = WindowEventHandler(self)
            self.window_conn = GetEvents(self.pBrowser.Document.window,
                                        sink=self.window_handler,
                                    interface=MSHTML.HTMLWindowEvents2)
        self.window_handler.addEventListener(event_name, event_fn)
        return event_name # hmmm...

    def getXmlHttpRequest(self):
        xml_svc_cls = components.classes[ \
            "@mozilla.org/xmlextras/xmlhttprequest;1"]
        return xml_svc_cls.createInstance(interfaces.nsIXMLHttpRequest)

    def getUri(self):
        return self.application

    def _loaded(self):

        print "loaded"

        if self.already_initialised:
            return
        self.already_initialised = True

        from __pyjamas__ import pygwt_processMetas, set_main_frame
        #from __pyjamas__ import set_gtk_module
        set_main_frame(self)
        #set_gtk_module(gtk)

        (pth, app) = os.path.split(self.application)
        if self.appdir:
            pth = os.path.abspath(self.appdir)
        sys.path.append(pth)

def MainWin(one_event):

    # Pump Messages
    msg = MSG()
    pMsg = pointer(msg)
    NULL = c_int(win32con.NULL)

    while windll.user32.GetMessageA( pMsg, NULL, 0, 0) != 0:

        windll.user32.TranslateMessage(pMsg)
        windll.user32.DispatchMessageA(pMsg)

        #print msg.message, msg.wParam, msg.lParam
        #if msg.message == 161: # win32con.WM_DESTROY:
        #    windll.user32.PostQuitMessage(0)

        if one_event:
            break

    return msg.wParam

class ContentInvoker:

    def __init__(self, node, event_fn):
        self._node = node
        self._event_fn = event_fn

    def handleEvent(self, event):
        self._event_fn(self._node, event, False)

global wv
wv = None

def is_loaded():
    return wv.already_initialised

def run(one_event=False, block=True):
    MainWin(one_event) # TODO: ignore block arg for now

def setup(application, appdir=None, width=800, height=600):

    global wv
    wv = Browser(application, appdir)

    wv.load_app()

    while 1:
        if is_loaded():
            return
        run(one_event=True)

<|endoftext|>


<commit_before>#!/usr/bin/env python

from distribute_setup import use_setuptools
use_setuptools()

from setuptools import setup, find_packages

VERSION = "0.8.4"
SHORT_DESCRIPTION = "Kegbot kegerator controller software"
LONG_DESCRIPTION = """This package contains Kegbot core controller and Django
frontend package.

Kegbot is a hardware and software system to record and monitor access to a beer
kegerator.  For more information and documentation, see http://kegbot.org/
"""

setup(
    name = "kegbot",
    version = VERSION,
    description = SHORT_DESCRIPTION,
    long_description = LONG_DESCRIPTION,
    author = "mike wakerly",
    author_email = "opensource@hoho.com",
    url = "http://kegbot.org/",
    packages = find_packages('src'),
    package_dir = {
      '' : 'src',
    },
    scripts = [
      'distribute_setup.py',
      'src/pykeg/bin/fb_publisher.py',
      'src/pykeg/bin/kegboard_daemon.py',
      'src/pykeg/bin/kegboard_monitor.py',
      'src/pykeg/bin/kegboard-tester.py',
      'src/pykeg/bin/kegbot-admin.py',
      'src/pykeg/bin/kegbot_core.py',
      'src/pykeg/bin/kegbot_master.py',
      'src/pykeg/bin/kegnetproxy.py',
      'src/pykeg/bin/lcd_daemon.py',
      'src/pykeg/bin/rfid_daemon.py',
      'src/pykeg/bin/sound_server.py',
    ],
    install_requires = [
      'django >= 1.3',
      'django-autoslug',
      'django-bootstrap-form',
      'django-debug-toolbar',
      'django-imagekit >= 1.0',
      'django-registration',
      'django-sentry',
      'django_extensions',
      'django-storages',
      'boto',

      # NOTE(mikey): socialregistration does not yet declare the
      # facebook-python-sdk prerequisite for itself.
      'facebook-python-sdk',
      'django-socialregistration >= 0.5.3',

      #'MySQL-python',
      #'pil',
      'protobuf >= 2.4.1',
      'pylcdui >= 0.5.5',
      #'pysqlite>=2.0.3',
      'python-gflags >= 1.3',
      'South >= 0.7.3',
      'Sphinx',
      'django_nose',
      #'python-openid >= 2.2.5',  # removeme once PIL package works
      'tweepy',
      'django-icanhaz',
      'pytz',
      'raven',
      'requests',  # needed by oauth

      # Celery and dependencies
      'Celery',
      'django-celery',
      'django-kombu',

      'poster',  # needed by foursquare
      'foursquare',

      # Tornado
      'tornado',
      'rjdj.djangotornado',
    ],
    dependency_links = [
        'https://github.com/mLewisLogic/foursquare/tarball/master#egg=foursquare',
        'https://github.com/rem/python-protobuf/tarball/master#egg=protobuf-2.4.1',
        'http://dist.repoze.org/PIL-1.1.6.tar.gz',
        'http://kegbot.org/kmedia/python-openid-2.2.5.tgz',
        'https://github.com/tzangms/django-bootstrap-form/tarball/master#egg=django-bootstrap-form',
        'https://github.com/rjdj/django-tornado/tarball/master#egg=rjdj.djangotornado',

        # Self-maintained package due to upstream issue:
        # http://github.com/facebook/python-sdk/issues/#issue/21
        'http://github.com/downloads/mik3y/python-sdk/facebook-python-sdk-0.1-1.tar.gz',
    ],
    include_package_data = True,
    entry_points = {
      'console_scripts': ['instance=django.core.management:execute_manager'],
    },

)
<commit_msg>setup: require imagekit 2.0<commit_after>#!/usr/bin/env python

from distribute_setup import use_setuptools
use_setuptools()

from setuptools import setup, find_packages

VERSION = "0.8.4"
SHORT_DESCRIPTION = "Kegbot kegerator controller software"
LONG_DESCRIPTION = """This package contains Kegbot core controller and Django
frontend package.

Kegbot is a hardware and software system to record and monitor access to a beer
kegerator.  For more information and documentation, see http://kegbot.org/
"""

setup(
    name = "kegbot",
    version = VERSION,
    description = SHORT_DESCRIPTION,
    long_description = LONG_DESCRIPTION,
    author = "mike wakerly",
    author_email = "opensource@hoho.com",
    url = "http://kegbot.org/",
    packages = find_packages('src'),
    package_dir = {
      '' : 'src',
    },
    scripts = [
      'distribute_setup.py',
      'src/pykeg/bin/fb_publisher.py',
      'src/pykeg/bin/kegboard_daemon.py',
      'src/pykeg/bin/kegboard_monitor.py',
      'src/pykeg/bin/kegboard-tester.py',
      'src/pykeg/bin/kegbot-admin.py',
      'src/pykeg/bin/kegbot_core.py',
      'src/pykeg/bin/kegbot_master.py',
      'src/pykeg/bin/kegnetproxy.py',
      'src/pykeg/bin/lcd_daemon.py',
      'src/pykeg/bin/rfid_daemon.py',
      'src/pykeg/bin/sound_server.py',
    ],
    install_requires = [
      'django >= 1.3',
      'django-autoslug',
      'django-bootstrap-form',
      'django-debug-toolbar',
      'django-imagekit >= 2.0',
      'django-registration',
      'django-sentry',
      'django_extensions',
      'django-storages',
      'boto',

      # NOTE(mikey): socialregistration does not yet declare the
      # facebook-python-sdk prerequisite for itself.
      'facebook-python-sdk',
      'django-socialregistration >= 0.5.3',

      #'MySQL-python',
      #'pil',
      'protobuf >= 2.4.1',
      'pylcdui >= 0.5.5',
      #'pysqlite>=2.0.3',
      'python-gflags >= 1.3',
      'South >= 0.7.3',
      'Sphinx',
      'django_nose',
      #'python-openid >= 2.2.5',  # removeme once PIL package works
      'tweepy',
      'django-icanhaz',
      'pytz',
      'raven',
      'requests',  # needed by oauth

      # Celery and dependencies
      'Celery',
      'django-celery',
      'django-kombu',

      'poster',  # needed by foursquare
      'foursquare',

      # Tornado
      'tornado',
      'rjdj.djangotornado',
    ],
    dependency_links = [
        'https://github.com/mLewisLogic/foursquare/tarball/master#egg=foursquare',
        'https://github.com/rem/python-protobuf/tarball/master#egg=protobuf-2.4.1',
        'http://dist.repoze.org/PIL-1.1.6.tar.gz',
        'http://kegbot.org/kmedia/python-openid-2.2.5.tgz',
        'https://github.com/tzangms/django-bootstrap-form/tarball/master#egg=django-bootstrap-form',
        'https://github.com/rjdj/django-tornado/tarball/master#egg=rjdj.djangotornado',

        # Self-maintained package due to upstream issue:
        # http://github.com/facebook/python-sdk/issues/#issue/21
        'http://github.com/downloads/mik3y/python-sdk/facebook-python-sdk-0.1-1.tar.gz',
    ],
    include_package_data = True,
    entry_points = {
      'console_scripts': ['instance=django.core.management:execute_manager'],
    },

)
<|endoftext|>