<commit_before>import os
from select import select
from subprocess import PIPE
import sys
from itertools import chain

from plumbum.commands.processes import run_proc, ProcessExecutionError
from plumbum.commands.base import AppendingStdoutRedirection, StdoutRedirection
from plumbum.lib import read_fd_decode_safely

class Future(object):
    """Represents a "future result" of a running process. It basically wraps a ``Popen``
    object and the expected exit code, and provides poll(), wait(), returncode, stdout,
    and stderr.
    """
    def __init__(self, proc, expected_retcode, timeout = None):
        self.proc = proc
        self._expected_retcode = expected_retcode
        self._timeout = timeout
        self._returncode = None
        self._stdout = None
        self._stderr = None
    def __repr__(self):
        return "<Future %r (%s)>" % (self.proc.argv, self._returncode if self.ready() else "running",)
    def poll(self):
        """Polls the underlying process for termination; returns ``False`` if still running,
        or ``True`` if terminated"""
        if self.proc.poll() is not None:
            self.wait()
        return self._returncode is not None
    ready = poll
    def wait(self):
        """Waits for the process to terminate; will raise a
        :class:`plumbum.commands.ProcessExecutionError` in case of failure"""
        if self._returncode is not None:
            return
        self._returncode, self._stdout, self._stderr = run_proc(self.proc,
            self._expected_retcode, self._timeout)
    @property
    def stdout(self):
        """The process' stdout; accessing this property will wait for the process to finish"""
        self.wait()
        return self._stdout
    @property
    def stderr(self):
        """The process' stderr; accessing this property will wait for the process to finish"""
        self.wait()
        return self._stderr
    @property
    def returncode(self):
        """The process' returncode; accessing this property will wait for the process to finish"""
        self.wait()
        return self._returncode

#===================================================================================================
# execution modifiers
#===================================================================================================

class ExecutionModifier(object):
    __slots__ = ()

    def __repr__(self):
        """Automatically creates a representation for given subclass with slots.
        Ignore hidden properties."""
        slots = {}
        for cls in self.__mro__:
            for prop in getattr(cls, "__slots__", ()):
                if prop[0] != '_':
                    slots[prop] = getattr(self, prop)
        mystrs = ("{0} = {1}".format(name, slots[name]) for name in slots)
        return "{0}({1})".format(self.__class__.__name__, ", ".join(mystrs))

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

class BG(ExecutionModifier):
    """
    An execution modifier that runs the given command in the background, returning a
    :class:`Future <plumbum.commands.Future>` object. In order to mimic shell syntax, it applies
    when you right-and it with a command. If you wish to expect a different return code
    (other than the normal success indicate by 0), use ``BG(retcode)``. Example::

        future = sleep[5] & BG       # a future expecting an exit code of 0
        future = sleep[5] & BG(7)    # a future expecting an exit code of 7

    .. note::

       When processes run in the **background** (either via ``popen`` or
       :class:`& BG <plumbum.commands.BG>`), their stdout/stderr pipes might fill up,
       causing them to hang. If you know a process produces output, be sure to consume it
       every once in a while, using a monitoring thread/reactor in the background.
       For more info, see `#48 <https://github.com/tomerfiliba/plumbum/issues/48>`_
    """
    __slots__ = ("retcode", "kargs")

    def __init__(self, retcode=0, **kargs):
        self.retcode = retcode
        self.kargs = kargs

    def __rand__(self, cmd):
        return Future(cmd.popen(**self.kargs), self.retcode)

BG = BG()

"""
An execution modifier that runs the given command in the background, returning a
:class:`Future <plumbum.commands.Future>` object. In order to mimic shell syntax, it applies
when you right-and it with a command. If you wish to expect a different return code
(other than the normal success indicate by 0), use ``BG(retcode)``. Example::

    future = sleep[5] & BG       # a future expecting an exit code of 0
    future = sleep[5] & BG(7)    # a future expecting an exit code of 7

.. note::

   When processes run in the **background** (either via ``popen`` or
   :class:`& BG <plumbum.commands.BG>`), their stdout/stderr pipes might fill up,
   causing them to hang. If you know a process produces output, be sure to consume it
   every once in a while, using a monitoring thread/reactor in the background.
   For more info, see `#48 <https://github.com/tomerfiliba/plumbum/issues/48>`_
"""

class FG(ExecutionModifier):
    """
    An execution modifier that runs the given command in the foreground, passing it the
    current process' stdin, stdout and stderr. Useful for interactive programs that require
    a TTY. There is no return value.

    In order to mimic shell syntax, it applies when you right-and it with a command.
    If you wish to expect a different return code (other than the normal success indicate by 0),
    use ``FG(retcode)``. Example::

        vim & FG       # run vim in the foreground, expecting an exit code of 0
        vim & FG(7)    # run vim in the foreground, expecting an exit code of 7
    """
    __slots__ = ("retcode",)

    def __init__(self, retcode=0):
        self.retcode = retcode

    def __rand__(self, cmd):
        cmd(retcode = self.retcode, stdin = None, stdout = None, stderr = None)

FG = FG()

class TEE(ExecutionModifier):
    """Run a command, dumping its stdout/stderr to the current process's stdout
    and stderr, but ALSO return them.  Useful for interactive programs that
    expect a TTY but also have valuable output.

    Use as:

        ls["-l"] & TEE

    Returns a tuple of (return code, stdout, stderr), just like ``run()``.
    """

    __slots__ = ("retcode", "buffered")

    def __init__(self, retcode=0, buffered=True):
        """`retcode` is the return code to expect to mean "success".  Set
        `buffered` to False to disable line-buffering the output, which may
        cause stdout and stderr to become more entangled than usual.
        """
        self.retcode = retcode
        self.buffered = buffered

    def __rand__(self, cmd):
        with cmd.bgrun(retcode=self.retcode, stdin=None, stdout=PIPE, stderr=PIPE) as p:
            outbuf = []
            errbuf = []
            out = p.stdout
            err = p.stderr
            buffers = {out: outbuf, err: errbuf}
            tee_to = {out: sys.stdout, err: sys.stderr}
            while p.poll() is None:
                ready, _, _ = select((out, err), (), ())
                for fd in ready:
                    buf = buffers[fd]
                    data, text = read_fd_decode_safely(fd, 4096)
                    if not data:  # eof
                        continue

                    # Python conveniently line-buffers stdout and stderr for
                    # us, so all we need to do is write to them

                    # This will automatically add up to three bytes if it cannot be decoded
                    tee_to[fd].write(text)

                    # And then "unbuffered" is just flushing after each write
                    if not self.buffered:
                        tee_to[fd].flush()

                    buf.append(data)

            stdout = ''.join([x.decode('utf-8') for x in outbuf])
            stderr = ''.join([x.decode('utf-8') for x in errbuf])
            return p.returncode, stdout, stderr

TEE = TEE()

class TF(ExecutionModifier):
    """
    An execution modifier that runs the given command, but returns True/False depending on the retcode.
    This returns True if the expected exit code is returned, and false if it is not.
    This is useful for checking true/false bash commands.

    If you wish to expect a different return code (other than the normal success indicate by 0),
    use ``TF(retcode)``. If you want to run the process in the forground, then use
    ``TF(FG=True)``.

    Example::

        local['touch']['/root/test'] & TF * Returns False, since this cannot be touched
        local['touch']['/root/test'] & TF(1) # Returns True
        local['touch']['/root/test'] & TF(FG=True) * Returns False, will show error message
    """

    __slots__ = ("retcode", "FG")

    def __init__(self, retcode=0, FG=False):
        """`retcode` is the return code to expect to mean "success".  Set
        `FG` to True to run in the foreground.
        """
        self.retcode = retcode
        self.FG = FG

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

    def __rand__(self, cmd):
        try:
            if self.FG:
                cmd(retcode = self.retcode, stdin = None, stdout = None, stderr = None)
            else:
                cmd(retcode = self.retcode)
            return True
        except ProcessExecutionError:
            return False

TF = TF()

class RETCODE(ExecutionModifier):
    """
    An execution modifier that runs the given command, causing it to run and return the retcode.
    This is useful for working with bash commands that have important retcodes but not very
    useful output.

    If you want to run the process in the forground, then use ``RETCODE(FG=True)``.

    Example::

        local['touch']['/root/test'] & RETCODE # Returns 1, since this cannot be touched
        local['touch']['/root/test'] & RETCODE(FG=True) * Returns 1, will show error message
    """

    __slots__ = ("foreground",)

    def __init__(self,  FG=False):
        """`FG` to True to run in the foreground.
        """
        self.foreground = FG

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

    def __rand__(self, cmd):
            if self.foreground:
                return cmd.run(retcode = None, stdin = None, stdout = None, stderr = None)[0]
            else:
                return cmd.run(retcode = None)[0]

RETCODE = RETCODE()

class NOHUP(ExecutionModifier):
    """
    An execution modifier that runs the given command in the background, disconnected
    from the current process, returning a
    standard popen object. It will keep running even if you close the current process.
    In order to slightly mimic shell syntax, it applies
    when you right-and it with a command. If you wish to use a diffent working directory
    or different stdout, stderr, you can use named arguments. The default is ``NOHUP(
    cwd=local.cwd, stdout='nohup.out', stderr=None)``. If stderr is None, stderr will be
    sent to stdout. Use ``os.devnull`` for null output. Will respect redirected output.
    Example::

        sleep[5] & NOHUP                       # Outputs to nohup.out
        sleep[5] & NOHUP(stdout=os.devnull)    # No output

    The equivelent bash command would be

    .. code-block:: bash

        nohup sleep 5 &

    """
    __slots__ = ('cwd', 'stdout', 'stderr', 'append')

    def __init__(self, cwd='.', stdout='nohup.out', stderr=None, append=True):
        """ Set ``cwd``, ``stdout``, or ``stderr``.
        Runs as a forked process. You can set ``append=False``, too.
        """
        self.cwd = cwd
        self.stdout = stdout
        self.stderr = stderr
        self.append = append

    def __rand__(self, cmd):
        if isinstance(cmd, StdoutRedirection):
            stdout = cmd.file
            append = False
            cmd = cmd.cmd
        elif isinstance(cmd, AppendingStdoutRedirection):
            stdout = cmd.file
            append = True
            cmd = cmd.cmd
        else:
            stdout = self.stdout
            append = self.append
        return cmd.nohup(cmd, self.cwd, stdout, self.stderr, append)

NOHUP = NOHUP()
<commit_msg>Fix for repr broken on modifiers, fixes #262<commit_after>import os
from select import select
from subprocess import PIPE
import sys
from itertools import chain

from plumbum.commands.processes import run_proc, ProcessExecutionError
from plumbum.commands.base import AppendingStdoutRedirection, StdoutRedirection
from plumbum.lib import read_fd_decode_safely

class Future(object):
    """Represents a "future result" of a running process. It basically wraps a ``Popen``
    object and the expected exit code, and provides poll(), wait(), returncode, stdout,
    and stderr.
    """
    def __init__(self, proc, expected_retcode, timeout = None):
        self.proc = proc
        self._expected_retcode = expected_retcode
        self._timeout = timeout
        self._returncode = None
        self._stdout = None
        self._stderr = None
    def __repr__(self):
        return "<Future %r (%s)>" % (self.proc.argv, self._returncode if self.ready() else "running",)
    def poll(self):
        """Polls the underlying process for termination; returns ``False`` if still running,
        or ``True`` if terminated"""
        if self.proc.poll() is not None:
            self.wait()
        return self._returncode is not None
    ready = poll
    def wait(self):
        """Waits for the process to terminate; will raise a
        :class:`plumbum.commands.ProcessExecutionError` in case of failure"""
        if self._returncode is not None:
            return
        self._returncode, self._stdout, self._stderr = run_proc(self.proc,
            self._expected_retcode, self._timeout)
    @property
    def stdout(self):
        """The process' stdout; accessing this property will wait for the process to finish"""
        self.wait()
        return self._stdout
    @property
    def stderr(self):
        """The process' stderr; accessing this property will wait for the process to finish"""
        self.wait()
        return self._stderr
    @property
    def returncode(self):
        """The process' returncode; accessing this property will wait for the process to finish"""
        self.wait()
        return self._returncode

#===================================================================================================
# execution modifiers
#===================================================================================================

class ExecutionModifier(object):
    __slots__ = ()

    def __repr__(self):
        """Automatically creates a representation for given subclass with slots.
        Ignore hidden properties."""
        slots = {}
        for cls in self.__class__.__mro__:
            for prop in getattr(cls, "__slots__", ()):
                if prop[0] != '_':
                    slots[prop] = getattr(self, prop)
        mystrs = ("{0} = {1}".format(name, slots[name]) for name in slots)
        return "{0}({1})".format(self.__class__.__name__, ", ".join(mystrs))

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

class BG(ExecutionModifier):
    """
    An execution modifier that runs the given command in the background, returning a
    :class:`Future <plumbum.commands.Future>` object. In order to mimic shell syntax, it applies
    when you right-and it with a command. If you wish to expect a different return code
    (other than the normal success indicate by 0), use ``BG(retcode)``. Example::

        future = sleep[5] & BG       # a future expecting an exit code of 0
        future = sleep[5] & BG(7)    # a future expecting an exit code of 7

    .. note::

       When processes run in the **background** (either via ``popen`` or
       :class:`& BG <plumbum.commands.BG>`), their stdout/stderr pipes might fill up,
       causing them to hang. If you know a process produces output, be sure to consume it
       every once in a while, using a monitoring thread/reactor in the background.
       For more info, see `#48 <https://github.com/tomerfiliba/plumbum/issues/48>`_
    """
    __slots__ = ("retcode", "kargs")

    def __init__(self, retcode=0, **kargs):
        self.retcode = retcode
        self.kargs = kargs

    def __rand__(self, cmd):
        return Future(cmd.popen(**self.kargs), self.retcode)

BG = BG()

"""
An execution modifier that runs the given command in the background, returning a
:class:`Future <plumbum.commands.Future>` object. In order to mimic shell syntax, it applies
when you right-and it with a command. If you wish to expect a different return code
(other than the normal success indicate by 0), use ``BG(retcode)``. Example::

    future = sleep[5] & BG       # a future expecting an exit code of 0
    future = sleep[5] & BG(7)    # a future expecting an exit code of 7

.. note::

   When processes run in the **background** (either via ``popen`` or
   :class:`& BG <plumbum.commands.BG>`), their stdout/stderr pipes might fill up,
   causing them to hang. If you know a process produces output, be sure to consume it
   every once in a while, using a monitoring thread/reactor in the background.
   For more info, see `#48 <https://github.com/tomerfiliba/plumbum/issues/48>`_
"""

class FG(ExecutionModifier):
    """
    An execution modifier that runs the given command in the foreground, passing it the
    current process' stdin, stdout and stderr. Useful for interactive programs that require
    a TTY. There is no return value.

    In order to mimic shell syntax, it applies when you right-and it with a command.
    If you wish to expect a different return code (other than the normal success indicate by 0),
    use ``FG(retcode)``. Example::

        vim & FG       # run vim in the foreground, expecting an exit code of 0
        vim & FG(7)    # run vim in the foreground, expecting an exit code of 7
    """
    __slots__ = ("retcode",)

    def __init__(self, retcode=0):
        self.retcode = retcode

    def __rand__(self, cmd):
        cmd(retcode = self.retcode, stdin = None, stdout = None, stderr = None)

FG = FG()

class TEE(ExecutionModifier):
    """Run a command, dumping its stdout/stderr to the current process's stdout
    and stderr, but ALSO return them.  Useful for interactive programs that
    expect a TTY but also have valuable output.

    Use as:

        ls["-l"] & TEE

    Returns a tuple of (return code, stdout, stderr), just like ``run()``.
    """

    __slots__ = ("retcode", "buffered")

    def __init__(self, retcode=0, buffered=True):
        """`retcode` is the return code to expect to mean "success".  Set
        `buffered` to False to disable line-buffering the output, which may
        cause stdout and stderr to become more entangled than usual.
        """
        self.retcode = retcode
        self.buffered = buffered

    def __rand__(self, cmd):
        with cmd.bgrun(retcode=self.retcode, stdin=None, stdout=PIPE, stderr=PIPE) as p:
            outbuf = []
            errbuf = []
            out = p.stdout
            err = p.stderr
            buffers = {out: outbuf, err: errbuf}
            tee_to = {out: sys.stdout, err: sys.stderr}
            while p.poll() is None:
                ready, _, _ = select((out, err), (), ())
                for fd in ready:
                    buf = buffers[fd]
                    data, text = read_fd_decode_safely(fd, 4096)
                    if not data:  # eof
                        continue

                    # Python conveniently line-buffers stdout and stderr for
                    # us, so all we need to do is write to them

                    # This will automatically add up to three bytes if it cannot be decoded
                    tee_to[fd].write(text)

                    # And then "unbuffered" is just flushing after each write
                    if not self.buffered:
                        tee_to[fd].flush()

                    buf.append(data)

            stdout = ''.join([x.decode('utf-8') for x in outbuf])
            stderr = ''.join([x.decode('utf-8') for x in errbuf])
            return p.returncode, stdout, stderr

TEE = TEE()

class TF(ExecutionModifier):
    """
    An execution modifier that runs the given command, but returns True/False depending on the retcode.
    This returns True if the expected exit code is returned, and false if it is not.
    This is useful for checking true/false bash commands.

    If you wish to expect a different return code (other than the normal success indicate by 0),
    use ``TF(retcode)``. If you want to run the process in the forground, then use
    ``TF(FG=True)``.

    Example::

        local['touch']['/root/test'] & TF * Returns False, since this cannot be touched
        local['touch']['/root/test'] & TF(1) # Returns True
        local['touch']['/root/test'] & TF(FG=True) * Returns False, will show error message
    """

    __slots__ = ("retcode", "FG")

    def __init__(self, retcode=0, FG=False):
        """`retcode` is the return code to expect to mean "success".  Set
        `FG` to True to run in the foreground.
        """
        self.retcode = retcode
        self.FG = FG

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

    def __rand__(self, cmd):
        try:
            if self.FG:
                cmd(retcode = self.retcode, stdin = None, stdout = None, stderr = None)
            else:
                cmd(retcode = self.retcode)
            return True
        except ProcessExecutionError:
            return False

TF = TF()

class RETCODE(ExecutionModifier):
    """
    An execution modifier that runs the given command, causing it to run and return the retcode.
    This is useful for working with bash commands that have important retcodes but not very
    useful output.

    If you want to run the process in the forground, then use ``RETCODE(FG=True)``.

    Example::

        local['touch']['/root/test'] & RETCODE # Returns 1, since this cannot be touched
        local['touch']['/root/test'] & RETCODE(FG=True) * Returns 1, will show error message
    """

    __slots__ = ("foreground",)

    def __init__(self,  FG=False):
        """`FG` to True to run in the foreground.
        """
        self.foreground = FG

    @classmethod
    def __call__(cls, *args, **kwargs):
        return cls(*args, **kwargs)

    def __rand__(self, cmd):
            if self.foreground:
                return cmd.run(retcode = None, stdin = None, stdout = None, stderr = None)[0]
            else:
                return cmd.run(retcode = None)[0]

RETCODE = RETCODE()

class NOHUP(ExecutionModifier):
    """
    An execution modifier that runs the given command in the background, disconnected
    from the current process, returning a
    standard popen object. It will keep running even if you close the current process.
    In order to slightly mimic shell syntax, it applies
    when you right-and it with a command. If you wish to use a diffent working directory
    or different stdout, stderr, you can use named arguments. The default is ``NOHUP(
    cwd=local.cwd, stdout='nohup.out', stderr=None)``. If stderr is None, stderr will be
    sent to stdout. Use ``os.devnull`` for null output. Will respect redirected output.
    Example::

        sleep[5] & NOHUP                       # Outputs to nohup.out
        sleep[5] & NOHUP(stdout=os.devnull)    # No output

    The equivelent bash command would be

    .. code-block:: bash

        nohup sleep 5 &

    """
    __slots__ = ('cwd', 'stdout', 'stderr', 'append')

    def __init__(self, cwd='.', stdout='nohup.out', stderr=None, append=True):
        """ Set ``cwd``, ``stdout``, or ``stderr``.
        Runs as a forked process. You can set ``append=False``, too.
        """
        self.cwd = cwd
        self.stdout = stdout
        self.stderr = stderr
        self.append = append

    def __rand__(self, cmd):
        if isinstance(cmd, StdoutRedirection):
            stdout = cmd.file
            append = False
            cmd = cmd.cmd
        elif isinstance(cmd, AppendingStdoutRedirection):
            stdout = cmd.file
            append = True
            cmd = cmd.cmd
        else:
            stdout = self.stdout
            append = self.append
        return cmd.nohup(cmd, self.cwd, stdout, self.stderr, append)

NOHUP = NOHUP()
<|endoftext|>


<commit_before>{
  'targets': [
    {
      'target_name': 'usb_bindings',
      'sources': [
        './src/node_usb.cc',
        './src/device.cc',
        './src/transfer.cc',
      ],
      'cflags_cc': [
        '-std=c++0x'
      ],
      'defines': [
        '_FILE_OFFSET_BITS=64',
        '_LARGEFILE_SOURCE',
      ],
      'include_dirs+': [
        'src/'
      ],
      'conditions' : [
          ['OS=="linux"', {
            'include_dirs+': [
              '<!@(pkg-config libusb-1.0 --cflags-only-I | sed s/-I//g)'
            ],
            'libraries': [
              '<!@(pkg-config libusb-1.0 --libs)'
            ],
            'defines': [
              'USE_POLL',
            ]
          }],
          ['OS=="mac"', {
            'include_dirs+': [
              '<!@(pkg-config libusb-1.0 --cflags-only-I | sed s/-I//g)'
            ],
            'libraries': [
              '<!@(pkg-config libusb-1.0 --libs)'
            ],
            'defines': [
              'USE_POLL',
            ]
          }],
          ['OS=="win"', {
            'variables': {
              # Path to extracted libusbx windows binary package from http://libusbx.org/
              'libusb_path': "C:/Program Files/libusb"
            },
            'defines':[
              'WIN32_LEAN_AND_MEAN'
            ],
            'include_dirs+': [
              '<(libusb_path)/include/libusbx-1.0'
            ],
            'msvs_settings': {
              'VCCLCompilerTool': {
                'AdditionalOptions': [ '/EHsc /MD' ],
              },
            },
            "conditions" : [
              ["target_arch=='ia32'", {
                'libraries': [
                   '<(libusb_path)/MS32/static/libusb-1.0.lib'
                ]
              }],
              ["target_arch=='x64'", {
                'libraries': [
                   '<(libusb_path)/MS64/static/libusb-1.0.lib'
                ]
              }]
            ]
          }]
      ]
    }
  ]
}
<commit_msg>Disable USE_POLL for now on Mac.<commit_after>{
  'targets': [
    {
      'target_name': 'usb_bindings',
      'sources': [
        './src/node_usb.cc',
        './src/device.cc',
        './src/transfer.cc',
      ],
      'cflags_cc': [
        '-std=c++0x'
      ],
      'defines': [
        '_FILE_OFFSET_BITS=64',
        '_LARGEFILE_SOURCE',
      ],
      'include_dirs+': [
        'src/'
      ],
      'conditions' : [
          ['OS=="linux"', {
            'include_dirs+': [
              '<!@(pkg-config libusb-1.0 --cflags-only-I | sed s/-I//g)'
            ],
            'libraries': [
              '<!@(pkg-config libusb-1.0 --libs)'
            ],
            'defines': [
              'USE_POLL',
            ]
          }],
          ['OS=="mac"', {
            'include_dirs+': [
              '<!@(pkg-config libusb-1.0 --cflags-only-I | sed s/-I//g)'
            ],
            'libraries': [
              '<!@(pkg-config libusb-1.0 --libs)'
            ],
          }],
          ['OS=="win"', {
            'variables': {
              # Path to extracted libusbx windows binary package from http://libusbx.org/
              'libusb_path': "C:/Program Files/libusb"
            },
            'defines':[
              'WIN32_LEAN_AND_MEAN'
            ],
            'include_dirs+': [
              '<(libusb_path)/include/libusbx-1.0'
            ],
            'msvs_settings': {
              'VCCLCompilerTool': {
                'AdditionalOptions': [ '/EHsc /MD' ],
              },
            },
            "conditions" : [
              ["target_arch=='ia32'", {
                'libraries': [
                   '<(libusb_path)/MS32/static/libusb-1.0.lib'
                ]
              }],
              ["target_arch=='x64'", {
                'libraries': [
                   '<(libusb_path)/MS64/static/libusb-1.0.lib'
                ]
              }]
            ]
          }]
      ]
    }
  ]
}
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

##############################################################################
#
# Sale - Product Variant Selection Assistant
# Copyright (C) 2016 OpusVL (<http://opusvl.com/>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp import models, fields, api
from openerp.exceptions import ValidationError

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    variant_assistant_product_template_id = fields.Many2one(
        string='Product Template',
        comodel_name='product.template',
        help='To use the variant assistant, select the top-level product template here',
    )

    variant_assistant_attribute_choice_ids = fields.One2many(
        comodel_name='sale.order.line.assistant.attribute.choice',
        inverse_name='sale_order_line_id',
        string='Choose attributes',
        invisible=[('variant_assistant_attribute_choice_ids', '=', False)],
        help='Now select the attribute values.  Once you select enough attributes to uniquely identify the product, it will be entered in the Product field',
    )

    @api.returns('product.attribute')
    def _assistant_attributes(self):
        return self.variant_assistant_product_template_id.attribute_line_ids.mapped('attribute_id')

    @api.returns('product.attribute.value')
    def _assistant_available_values(self, attribute):
        template = self.variant_assistant_product_template_id
        return attribute.value_ids.filtered(lambda v: v in template.attribute_line_ids.mapped('value_ids'))

    @api.onchange('variant_assistant_product_template_id')
    def _onchange_product_template_id(self):
        changes = [(2, i, False) for i in self.variant_assistant_attribute_choice_ids.ids]
        attrs = self._assistant_attributes()
        if attrs:
             changes.extend((0, False, {"attribute_id": i}) for i in attrs.ids)
        self.update({'variant_assistant_attribute_choice_ids': changes})

class SaleOrderLineAssistantAttributeChoice(models.Model):
    _name = 'sale.order.line.assistant.attribute.choice'

    sale_order_line_id = fields.Many2one(
        string='Sale Order Line',
        comodel_name='sale.order.line',
    )
    product_template_id = fields.Many2one(
        string='Product Template',
        readonly=True,
        related='sale_order_line_id.variant_assistant_product_template_id',
    )
    attribute_id = fields.Many2one(
        string='Attribute',
        comodel_name='product.attribute',
        required=True,
    )

    value_id = fields.Many2one(
        string='Value',
        comodel_name='product.attribute.value',
    )

    @api.one
    @api.constrains('product_template_id', 'attribute_id', 'value_id')
    def _check_attributes(self):
        if self.attribute_id not in self.product_template_id.attribute_line_ids.mapped('attribute_id'):
            raise ValidationError('Attribute must match product template')
        if self.value_id.attribute_id != self.attribute_id:
            raise ValidationError('Value must match attribute')
        if self.value_id not in self.product_template_id.attribute_line_ids.mapped('value_ids'):
            raise ValidationError("Value must match product")

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>Pre-select attribute value if only one available.<commit_after># -*- coding: utf-8 -*-

##############################################################################
#
# Sale - Product Variant Selection Assistant
# Copyright (C) 2016 OpusVL (<http://opusvl.com/>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp import models, fields, api
from openerp.exceptions import ValidationError

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    variant_assistant_product_template_id = fields.Many2one(
        string='Product Template',
        comodel_name='product.template',
        help='To use the variant assistant, select the top-level product template here',
    )

    variant_assistant_attribute_choice_ids = fields.One2many(
        comodel_name='sale.order.line.assistant.attribute.choice',
        inverse_name='sale_order_line_id',
        string='Choose attributes',
        invisible=[('variant_assistant_attribute_choice_ids', '=', False)],
        help='Now select the attribute values.  Once you select enough attributes to uniquely identify the product, it will be entered in the Product field',
    )

    @api.returns('product.attribute')
    def _assistant_attributes(self):
        return self.variant_assistant_product_template_id.attribute_line_ids.mapped('attribute_id')

    @api.returns('product.attribute.value')
    def _assistant_available_values(self, attribute):
        template = self.variant_assistant_product_template_id
        return attribute.value_ids.filtered(lambda v: v in template.attribute_line_ids.mapped('value_ids'))

    @api.onchange('variant_assistant_product_template_id')
    def _onchange_product_template_id(self):
        changes = [(2, i, False) for i in self.variant_assistant_attribute_choice_ids.ids]
        attrs = self._assistant_attributes()
        for attr in attrs:
            choice_data = {"attribute_id": attr.id}
            options = self._assistant_available_values(attr)
            if len(options) == 1:
                choice_data['value_id'] = options.id
            changes.append((0, False, choice_data))
        self.update({'variant_assistant_attribute_choice_ids': changes})

class SaleOrderLineAssistantAttributeChoice(models.Model):
    _name = 'sale.order.line.assistant.attribute.choice'

    sale_order_line_id = fields.Many2one(
        string='Sale Order Line',
        comodel_name='sale.order.line',
    )
    product_template_id = fields.Many2one(
        string='Product Template',
        readonly=True,
        related='sale_order_line_id.variant_assistant_product_template_id',
    )
    attribute_id = fields.Many2one(
        string='Attribute',
        comodel_name='product.attribute',
        required=True,
    )

    value_id = fields.Many2one(
        string='Value',
        comodel_name='product.attribute.value',
    )

    @api.one
    @api.constrains('product_template_id', 'attribute_id', 'value_id')
    def _check_attributes(self):
        if self.attribute_id not in self.product_template_id.attribute_line_ids.mapped('attribute_id'):
            raise ValidationError('Attribute must match product template')
        if self.value_id.attribute_id != self.attribute_id:
            raise ValidationError('Value must match attribute')
        if self.value_id not in self.product_template_id.attribute_line_ids.mapped('value_ids'):
            raise ValidationError("Value must match product")

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>"""
Atmosphere api email
"""
from rest_framework.response import Response
from rest_framework import status
from django.template.loader import render_to_string
from django.template import Context

from threepio import logger

from iplantauth.protocol.ldap import lookupEmail

from core.models import AtmosphereUser as User
from core.email import email_admin, resource_request_email

from api import failure_response
from api.v1.views.base import AuthAPIView

class Feedback(AuthAPIView):

    """
    Post feedback via RESTful API
    """

    def post(self, request):
        """
        Creates a new feedback email and sends it to admins.
        """
        required = ["message", "user-interface"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        result = self._email(request,
                             request.user.username,
                             lookupEmail(request.user.username),
                             request.data["message"],
                             request.data)
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, username, user_email, message):
        """
        Sends an email to support based on feedback from a client machine

        Returns a response.
        """
        user = User.objects.get(username=username)
        subject = 'Subject: Atmosphere Client Feedback from %s' % username
        context = {
            "user": user,
            "feedback": message
        }
        body = render_to_string("core/email/feedback.html",
                                context=Context(context))
        email_success = email_admin(request, subject, body, request_tracker=True)
        if email_success:
            resp = {'result':
                    {'code': 'success',
                        'meta': '',
                        'value': (
                            'Thank you for your feedback! '
                            'Support has been notified.')}}
        else:
            resp = {'result':
                    {'code': 'failed',
                     'meta': '',
                     'value': 'Failed to send feedback!'}}
        return resp

class QuotaEmail(AuthAPIView):

    """
    Post Quota Email via RESTful API.
    """

    def post(self, request):
        """
        Creates a new Quota Request email and sends it to admins.
        """
        required = ["quota", "reason"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        logger.debug("request.data = %s" % (str(request.data)))
        result = self._email(request,
                             request.user.username,
                             request.data["quota"],
                             request.data["reason"])
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, username, new_resource, reason):
        """
        Processes resource request increases. Sends email to atmo@iplantc.org

        Returns a response.
        """
        return resource_request_email(request, username, new_resource, reason)

class SupportEmail(AuthAPIView):

    def post(self, request):
        """
        Creates a new support email and sends it to admins.

        Post Support Email via RESTful API
        """
        required = ["message", "subject","user-interface"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        result = self._email(request,
                             request.data["subject"],
                             request.data["message"],
                             request.data)
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, subject, message):
        """
        Sends an email to support.

        POST Params expected:
        * user
        * message
        * subject

        Returns a response.
        """
        email_success = email_admin(request, subject, message)
        return {"email_sent": email_success}

def check_missing_keys(data, required_keys):
    """
    Return any missing required post key names.
    """
    return [key for key in required_keys
            # Key must exist and have a non-empty value.
            if key not in data or
            (isinstance(data[key], str) and len(data[key]) > 0)]

def keys_not_found(missing_keys):
    return failure_response(
        status.HTTP_400_BAD_REQUEST,
        "Missing required POST data variables : %s" % missing_keys)
<commit_msg>Fix feedback forms, too many arguments<commit_after>"""
Atmosphere api email
"""
from rest_framework.response import Response
from rest_framework import status
from django.template.loader import render_to_string
from django.template import Context

from threepio import logger

from iplantauth.protocol.ldap import lookupEmail

from core.models import AtmosphereUser as User
from core.email import email_admin, resource_request_email

from api import failure_response
from api.v1.views.base import AuthAPIView

class Feedback(AuthAPIView):

    """
    Post feedback via RESTful API
    """

    def post(self, request):
        """
        Creates a new feedback email and sends it to admins.
        """
        required = ["message", "user-interface"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        result = self._email(request,
                             request.user.username,
                             lookupEmail(request.user.username),
                             request.data["message"])
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, username, user_email, message):
        """
        Sends an email to support based on feedback from a client machine

        Returns a response.
        """
        user = User.objects.get(username=username)
        subject = 'Subject: Atmosphere Client Feedback from %s' % username
        context = {
            "user": user,
            "feedback": message
        }
        body = render_to_string("core/email/feedback.html",
                                context=Context(context))
        email_success = email_admin(request, subject, body, request_tracker=True)
        if email_success:
            resp = {'result':
                    {'code': 'success',
                        'meta': '',
                        'value': (
                            'Thank you for your feedback! '
                            'Support has been notified.')}}
        else:
            resp = {'result':
                    {'code': 'failed',
                     'meta': '',
                     'value': 'Failed to send feedback!'}}
        return resp

class QuotaEmail(AuthAPIView):

    """
    Post Quota Email via RESTful API.
    """

    def post(self, request):
        """
        Creates a new Quota Request email and sends it to admins.
        """
        required = ["quota", "reason"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        logger.debug("request.data = %s" % (str(request.data)))
        result = self._email(request,
                             request.user.username,
                             request.data["quota"],
                             request.data["reason"])
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, username, new_resource, reason):
        """
        Processes resource request increases. Sends email to atmo@iplantc.org

        Returns a response.
        """
        return resource_request_email(request, username, new_resource, reason)

class SupportEmail(AuthAPIView):

    def post(self, request):
        """
        Creates a new support email and sends it to admins.

        Post Support Email via RESTful API
        """
        required = ["message", "subject","user-interface"]
        missing_keys = check_missing_keys(request.data, required)
        if missing_keys:
            return keys_not_found(missing_keys)
        result = self._email(request,
                             request.data["subject"],
                             request.data["message"])
        return Response(result, status=status.HTTP_201_CREATED)

    def _email(self, request, subject, message):
        """
        Sends an email to support.

        POST Params expected:
        * user
        * message
        * subject

        Returns a response.
        """
        email_success = email_admin(request, subject, message)
        return {"email_sent": email_success}

def check_missing_keys(data, required_keys):
    """
    Return any missing required post key names.
    """
    return [key for key in required_keys
            # Key must exist and have a non-empty value.
            if key not in data or
            (isinstance(data[key], str) and len(data[key]) > 0)]

def keys_not_found(missing_keys):
    return failure_response(
        status.HTTP_400_BAD_REQUEST,
        "Missing required POST data variables : %s" % missing_keys)
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Test that autopep8 runs without crashing on various Python files."""

import contextlib
import difflib
import os
import re
import sys
import subprocess
import tempfile
import tokenize

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

@contextlib.contextmanager
def red(file_object):
    """Red context."""
    if file_object.isatty():
        RED = '\033[31m'
        END = '\033[0m'
    else:
        RED = ''
        END = ''

    try:
        file_object.flush()
        file_object.write(RED)
        file_object.flush()
        yield
    finally:
        file_object.flush()
        file_object.write(END)
        file_object.flush()

def run(filename, fast_check=False, passes=2000,
        ignore='', check_ignore='', verbose=False,
        compare_bytecode=False):
    """Run autopep8 on file at filename.

    Return True on success.

    """
    ignore_option = '--ignore=' + ignore

    autopep8_path = os.path.split(os.path.abspath(
        os.path.dirname(__file__)))[0]
    autoppe8_bin = os.path.join(autopep8_path, 'autopep8.py')
    command = ([autoppe8_bin] + (['--verbose'] if verbose else []) +
               ['--pep8-passes={p}'.format(p=passes),
                ignore_option, filename])

    if fast_check:
        if 0 != subprocess.call(command + ['--diff']):
            sys.stderr.write('autopep8 crashed on ' + filename + '\n')
            return False
    else:
        with tempfile.NamedTemporaryFile(suffix='.py') as tmp_file:
            if 0 != subprocess.call(command, stdout=tmp_file):
                sys.stderr.write('autopep8 crashed on ' + filename + '\n')
                return False

            with red(sys.stdout):
                if 0 != subprocess.call(['pep8', ignore_option + check_ignore,
                                         '--show-source', tmp_file.name],
                                        stdout=sys.stdout):
                    sys.stderr.write('autopep8 did not completely fix ' +
                                     filename + '\n')

            try:
                if check_syntax(filename):
                    try:
                        check_syntax(tmp_file.name, raise_error=True)
                    except (SyntaxError, TypeError,
                            UnicodeDecodeError) as exception:
                        sys.stderr.write('autopep8 broke ' + filename + '\n' +
                                         str(exception) + '\n')
                        return False

                    if compare_bytecode:
                        before_bytecode = disassemble(filename)
                        after_bytecode = disassemble(tmp_file.name)
                        if before_bytecode != after_bytecode:
                            sys.stderr.write(
                                'New bytecode does not match original ' +
                                filename + '\n' +
                                ''.join(difflib.unified_diff(
                                    before_bytecode.splitlines(True),
                                    after_bytecode.splitlines(True))))
                            return False
            except IOError as exception:
                sys.stderr.write(str(exception) + '\n')

    return True

def _detect_encoding(filename):
    """Return file encoding."""
    try:
        # Python 3
        try:
            with open(filename, 'rb') as input_file:
                encoding = tokenize.detect_encoding(input_file.readline)[0]

                # Check for correctness of encoding
                import io
                with io.TextIOWrapper(input_file, encoding) as wrapper:
                    wrapper.read()

            return encoding
        except (SyntaxError, LookupError, UnicodeDecodeError):
            return 'latin-1'
    except AttributeError:
        return 'utf-8'

def open_with_encoding(filename, encoding, mode='r'):
    """Open file with a specific encoding."""
    try:
        # Python 3
        return open(filename, mode=mode, encoding=encoding)
    except TypeError:
        return open(filename, mode=mode)

def check_syntax(filename, raise_error=False):
    """Return True if syntax is okay."""
    with open_with_encoding(
            filename, _detect_encoding(filename)) as input_file:
        try:
            compile(input_file.read(), '<string>', 'exec')
            return True
        except (SyntaxError, TypeError, UnicodeDecodeError):
            if raise_error:
                raise
            else:
                return False

def disassemble(filename):
    """dis, but without line numbers."""
    with open_with_encoding(filename, _detect_encoding(filename)) as f:
        code = compile(f.read(), '<string>', 'exec')

    return filter_disassembly('\n'.join(_disassemble(code)))

def filter_disassembly(text):
    """Filter out innocuous differences."""
    # Ignore formatting of docstrings. We modify docstrings for indentation and
    # trailing whitespace.
    lines = text.splitlines()
    for index, current_line in enumerate(lines):
        tokens = current_line.split()
        if (len(tokens) > 3 and
                tokens[1] == 'STORE_NAME' and tokens[3] == '(__doc__)'):
            fixed = re.sub(r'\s', '', lines[index - 1])
            lines[index - 1] = fixed.replace(
                r'\n', '').replace(r'\r', '').replace(r'\t', '')

    return '\n'.join(lines)

def _disassemble(code):
    """Disassemble a code object."""
    sio = StringIO()

    import dis
    findlinestarts = dis.findlinestarts
    dis.findlinestarts = lambda _: {}
    sys.stdout, sio = sio, sys.stdout
    try:
        dis.dis(code)
    finally:
        sys.stdout, sio = sio, sys.stdout
        dis.findlinestarts = findlinestarts

    disassembled_code = [
        re.sub('<code object .* line [0-9]+>',
               '<code object>',  sio.getvalue())]

    for c in code.co_consts:
        if hasattr(c, 'co_code'):
            disassembled_code += _disassemble(c)

    return disassembled_code

def process_args():
    """Return processed arguments (options and positional arguments)."""
    import optparse
    parser = optparse.OptionParser()
    parser.add_option('--fast-check', action='store_true',
                      help='ignore incomplete PEP8 fixes and broken files')
    parser.add_option('--ignore',
                      help='comma-separated errors to ignore',
                      default='')
    parser.add_option('--check-ignore',
                      help='comma-separated errors to ignore when checking '
                           'for completeness',
                      default='')
    parser.add_option('-p', '--pep8-passes',
                      help='maximum number of additional pep8 passes'
                           ' (default: %default)',
                      default=2000)
    parser.add_option('--compare-bytecode', action='store_true',
                      help='compare bytecode before and after fixes; '
                           'should be used with '
                           '--ignore=E711,E721,W601,W602,W604')

    parser.add_option(
        '--timeout',
        help='stop testing additional files after this amount of time '
             '(default: %default)',
        default=-1,
        type=float)

    parser.add_option('-v', '--verbose', action='store_true',
                      help='print verbose messages')

    return parser.parse_args()

class TimeoutException(Exception):

    """Timeout exception."""

def timeout(_, __):
    raise TimeoutException()

def check(opts, args):
    """Run recursively run autopep8 on directory of files.

    Return False if the fix results in broken syntax.

    """
    if args:
        dir_paths = args
    else:
        dir_paths = sys.path

    filenames = dir_paths
    completed_filenames = set()

    try:
        import signal
        if opts.timeout > 0:
            signal.signal(signal.SIGALRM, timeout)
            signal.alarm(int(opts.timeout))

        while filenames:
            name = os.path.realpath(filenames.pop(0))
            if name in completed_filenames:
                sys.stderr.write(
                    '--->  Skipping previously tested ' + name + '\n')
                continue
            else:
                completed_filenames.update(name)

            try:
                is_directory = os.path.isdir(name)
            except UnicodeEncodeError:
                continue

            if is_directory:
                for root, directories, children in os.walk(name):
                    filenames += [os.path.join(root, f) for f in children
                                  if f.endswith('.py') and
                                  not f.startswith('.')]
                    for d in directories:
                        if d.startswith('.'):
                            directories.remove(d)
            else:
                sys.stderr.write('--->  Testing with ')
                try:
                    sys.stderr.write(name)
                except UnicodeEncodeError:
                    sys.stderr.write('...')
                sys.stderr.write('\n')

                if not run(os.path.join(name),
                           fast_check=opts.fast_check,
                           passes=opts.pep8_passes,
                           ignore=opts.ignore,
                           check_ignore=opts.check_ignore,
                           verbose=opts.verbose,
                           compare_bytecode=opts.compare_bytecode):
                    return False
    except TimeoutException:
        sys.stderr.write('Timed out\n')
    finally:
        if opts.timeout > 0:
            signal.alarm(0)

    return True

def main():
    """Run main."""
    return 0 if check(*process_args()) else 1

if __name__ == '__main__':
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        sys.exit(1)
<commit_msg>Pass through "--aggressive" option<commit_after>#!/usr/bin/env python
"""Test that autopep8 runs without crashing on various Python files."""

import contextlib
import difflib
import os
import re
import sys
import subprocess
import tempfile
import tokenize

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

@contextlib.contextmanager
def red(file_object):
    """Red context."""
    if file_object.isatty():
        RED = '\033[31m'
        END = '\033[0m'
    else:
        RED = ''
        END = ''

    try:
        file_object.flush()
        file_object.write(RED)
        file_object.flush()
        yield
    finally:
        file_object.flush()
        file_object.write(END)
        file_object.flush()

def run(filename, fast_check=False, passes=2000,
        ignore='', check_ignore='', verbose=False,
        compare_bytecode=False,
        aggressive=False):
    """Run autopep8 on file at filename.

    Return True on success.

    """
    ignore_option = '--ignore=' + ignore

    autopep8_path = os.path.split(os.path.abspath(
        os.path.dirname(__file__)))[0]
    autoppe8_bin = os.path.join(autopep8_path, 'autopep8.py')
    command = ([autoppe8_bin] + (['--verbose'] if verbose else []) +
               ['--pep8-passes={p}'.format(p=passes),
                ignore_option, filename] +
               (['--aggressive'] if aggressive else []))

    if fast_check:
        if 0 != subprocess.call(command + ['--diff']):
            sys.stderr.write('autopep8 crashed on ' + filename + '\n')
            return False
    else:
        with tempfile.NamedTemporaryFile(suffix='.py') as tmp_file:
            if 0 != subprocess.call(command, stdout=tmp_file):
                sys.stderr.write('autopep8 crashed on ' + filename + '\n')
                return False

            with red(sys.stdout):
                if 0 != subprocess.call(['pep8', ignore_option + check_ignore,
                                         '--show-source', tmp_file.name],
                                        stdout=sys.stdout):
                    sys.stderr.write('autopep8 did not completely fix ' +
                                     filename + '\n')

            try:
                if check_syntax(filename):
                    try:
                        check_syntax(tmp_file.name, raise_error=True)
                    except (SyntaxError, TypeError,
                            UnicodeDecodeError) as exception:
                        sys.stderr.write('autopep8 broke ' + filename + '\n' +
                                         str(exception) + '\n')
                        return False

                    if compare_bytecode:
                        before_bytecode = disassemble(filename)
                        after_bytecode = disassemble(tmp_file.name)
                        if before_bytecode != after_bytecode:
                            sys.stderr.write(
                                'New bytecode does not match original ' +
                                filename + '\n' +
                                ''.join(difflib.unified_diff(
                                    before_bytecode.splitlines(True),
                                    after_bytecode.splitlines(True))))
                            return False
            except IOError as exception:
                sys.stderr.write(str(exception) + '\n')

    return True

def _detect_encoding(filename):
    """Return file encoding."""
    try:
        # Python 3
        try:
            with open(filename, 'rb') as input_file:
                encoding = tokenize.detect_encoding(input_file.readline)[0]

                # Check for correctness of encoding
                import io
                with io.TextIOWrapper(input_file, encoding) as wrapper:
                    wrapper.read()

            return encoding
        except (SyntaxError, LookupError, UnicodeDecodeError):
            return 'latin-1'
    except AttributeError:
        return 'utf-8'

def open_with_encoding(filename, encoding, mode='r'):
    """Open file with a specific encoding."""
    try:
        # Python 3
        return open(filename, mode=mode, encoding=encoding)
    except TypeError:
        return open(filename, mode=mode)

def check_syntax(filename, raise_error=False):
    """Return True if syntax is okay."""
    with open_with_encoding(
            filename, _detect_encoding(filename)) as input_file:
        try:
            compile(input_file.read(), '<string>', 'exec')
            return True
        except (SyntaxError, TypeError, UnicodeDecodeError):
            if raise_error:
                raise
            else:
                return False

def disassemble(filename):
    """dis, but without line numbers."""
    with open_with_encoding(filename, _detect_encoding(filename)) as f:
        code = compile(f.read(), '<string>', 'exec')

    return filter_disassembly('\n'.join(_disassemble(code)))

def filter_disassembly(text):
    """Filter out innocuous differences."""
    # Ignore formatting of docstrings. We modify docstrings for indentation and
    # trailing whitespace.
    lines = text.splitlines()
    for index, current_line in enumerate(lines):
        tokens = current_line.split()
        if (len(tokens) > 3 and
                tokens[1] == 'STORE_NAME' and tokens[3] == '(__doc__)'):
            fixed = re.sub(r'\s', '', lines[index - 1])
            lines[index - 1] = fixed.replace(
                r'\n', '').replace(r'\r', '').replace(r'\t', '')

    return '\n'.join(lines)

def _disassemble(code):
    """Disassemble a code object."""
    sio = StringIO()

    import dis
    findlinestarts = dis.findlinestarts
    dis.findlinestarts = lambda _: {}
    sys.stdout, sio = sio, sys.stdout
    try:
        dis.dis(code)
    finally:
        sys.stdout, sio = sio, sys.stdout
        dis.findlinestarts = findlinestarts

    disassembled_code = [
        re.sub('<code object .* line [0-9]+>',
               '<code object>',  sio.getvalue())]

    for c in code.co_consts:
        if hasattr(c, 'co_code'):
            disassembled_code += _disassemble(c)

    return disassembled_code

def process_args():
    """Return processed arguments (options and positional arguments)."""
    import optparse
    parser = optparse.OptionParser()
    parser.add_option('--fast-check', action='store_true',
                      help='ignore incomplete PEP8 fixes and broken files')
    parser.add_option('--ignore',
                      help='comma-separated errors to ignore',
                      default='')
    parser.add_option('--check-ignore',
                      help='comma-separated errors to ignore when checking '
                           'for completeness',
                      default='')
    parser.add_option('-p', '--pep8-passes',
                      help='maximum number of additional pep8 passes'
                           ' (default: %default)',
                      default=2000)
    parser.add_option('--compare-bytecode', action='store_true',
                      help='compare bytecode before and after fixes; '
                           'should be used with '
                           '--ignore=E711,E721,W601,W602,W604')
    parser.add_option('--aggressive', action='store_true',
                      help='run autopep8 in aggressive mode')

    parser.add_option(
        '--timeout',
        help='stop testing additional files after this amount of time '
             '(default: %default)',
        default=-1,
        type=float)

    parser.add_option('-v', '--verbose', action='store_true',
                      help='print verbose messages')

    return parser.parse_args()

class TimeoutException(Exception):

    """Timeout exception."""

def timeout(_, __):
    raise TimeoutException()

def check(opts, args):
    """Run recursively run autopep8 on directory of files.

    Return False if the fix results in broken syntax.

    """
    if args:
        dir_paths = args
    else:
        dir_paths = sys.path

    filenames = dir_paths
    completed_filenames = set()

    try:
        import signal
        if opts.timeout > 0:
            signal.signal(signal.SIGALRM, timeout)
            signal.alarm(int(opts.timeout))

        while filenames:
            name = os.path.realpath(filenames.pop(0))
            if name in completed_filenames:
                sys.stderr.write(
                    '--->  Skipping previously tested ' + name + '\n')
                continue
            else:
                completed_filenames.update(name)

            try:
                is_directory = os.path.isdir(name)
            except UnicodeEncodeError:
                continue

            if is_directory:
                for root, directories, children in os.walk(name):
                    filenames += [os.path.join(root, f) for f in children
                                  if f.endswith('.py') and
                                  not f.startswith('.')]
                    for d in directories:
                        if d.startswith('.'):
                            directories.remove(d)
            else:
                sys.stderr.write('--->  Testing with ')
                try:
                    sys.stderr.write(name)
                except UnicodeEncodeError:
                    sys.stderr.write('...')
                sys.stderr.write('\n')

                if not run(os.path.join(name),
                           fast_check=opts.fast_check,
                           passes=opts.pep8_passes,
                           ignore=opts.ignore,
                           check_ignore=opts.check_ignore,
                           verbose=opts.verbose,
                           compare_bytecode=opts.compare_bytecode,
                           aggressive=opts.aggressive):
                    return False
    except TimeoutException:
        sys.stderr.write('Timed out\n')
    finally:
        if opts.timeout > 0:
            signal.alarm(0)

    return True

def main():
    """Run main."""
    return 0 if check(*process_args()) else 1

if __name__ == '__main__':
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        sys.exit(1)
<|endoftext|>


<commit_before>from __future__ import absolute_import
from pony.py23compat import PY2, imap, basestring, buffer

from decimal import Decimal, InvalidOperation
from datetime import datetime, date, time, timedelta
from uuid import UUID

import warnings
warnings.filterwarnings('ignore', '^Table.+already exists$', Warning, '^pony\\.orm\\.dbapiprovider$')

try:
    import MySQLdb as mysql_module
except ImportError as e:
    try:
        import pymysql as mysql_module
    except ImportError:
        raise ImportError('No module named MySQLdb or pymysql found')
    else:
        import pymysql.converters as mysql_converters
        from pymysql.constants import FIELD_TYPE, FLAG, CLIENT
        if PY2:
            mysql_converters.encoders[buffer] = lambda val: mysql_converters.escape_str(str(val))
        mysql_converters.encoders[timedelta] = lambda val: mysql_converters.escape_str(timedelta2str(val))
        mysql_module_name = 'pymysql'
else:
    import MySQLdb.converters as mysql_converters
    from MySQLdb.constants import FIELD_TYPE, FLAG, CLIENT
    mysql_module_name = 'MySQLdb'
    from _mysql import string_literal

from pony.orm import core, dbschema, dbapiprovider
from pony.orm.core import log_orm, log_sql, OperationalError
from pony.orm.dbapiprovider import DBAPIProvider, Pool, get_version_tuple, wrap_dbapi_exceptions
from pony.orm.sqltranslation import SQLTranslator
from pony.orm.sqlbuilding import SQLBuilder, join
from pony.utils import throw
from pony.converting import str2timedelta, timedelta2str

class MySQLColumn(dbschema.Column):
    auto_template = '%(type)s PRIMARY KEY AUTO_INCREMENT'

class MySQLSchema(dbschema.DBSchema):
    dialect = 'MySQL'
    inline_fk_syntax = False
    column_class = MySQLColumn

class MySQLTranslator(SQLTranslator):
    dialect = 'MySQL'

class MySQLBuilder(SQLBuilder):
    dialect = 'MySQL'
    def CONCAT(builder, *args):
        return 'concat(',  join(', ', imap(builder, args)), ')'
    def TRIM(builder, expr, chars=None):
        if chars is None: return 'trim(', builder(expr), ')'
        return 'trim(both ', builder(chars), ' from ' ,builder(expr), ')'
    def LTRIM(builder, expr, chars=None):
        if chars is None: return 'ltrim(', builder(expr), ')'
        return 'trim(leading ', builder(chars), ' from ' ,builder(expr), ')'
    def RTRIM(builder, expr, chars=None):
        if chars is None: return 'rtrim(', builder(expr), ')'
        return 'trim(trailing ', builder(chars), ' from ' ,builder(expr), ')'
    def YEAR(builder, expr):
        return 'year(', builder(expr), ')'
    def MONTH(builder, expr):
        return 'month(', builder(expr), ')'
    def DAY(builder, expr):
        return 'day(', builder(expr), ')'
    def HOUR(builder, expr):
        return 'hour(', builder(expr), ')'
    def MINUTE(builder, expr):
        return 'minute(', builder(expr), ')'
    def SECOND(builder, expr):
        return 'second(', builder(expr), ')'
    def DATE_ADD(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_ADD(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'ADDTIME(', builder(expr), ', ', builder(delta), ')'
    def DATE_SUB(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_SUB(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'SUBTIME(', builder(expr), ', ', builder(delta), ')'
    def DATETIME_ADD(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_ADD(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'ADDTIME(', builder(expr), ', ', builder(delta), ')'
    def DATETIME_SUB(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_SUB(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'SUBTIME(', builder(expr), ', ', builder(delta), ')'

class MySQLStrConverter(dbapiprovider.StrConverter):
    def sql_type(converter):
        result = 'VARCHAR(%d)' % converter.max_len if converter.max_len else 'LONGTEXT'
        if converter.db_encoding: result += ' CHARACTER SET %s' % converter.db_encoding
        return result

if PY2:
    class MySQLLongConverter(dbapiprovider.IntConverter):
        def sql_type(converter):
            return 'BIGINT'

class MySQLRealConverter(dbapiprovider.RealConverter):
    def sql_type(converter):
        return 'DOUBLE'

class MySQLBlobConverter(dbapiprovider.BlobConverter):
    def sql_type(converter):
        return 'LONGBLOB'

class MySQLTimeConverter(dbapiprovider.TimeConverter):
    def sql2py(converter, val):
        if isinstance(val, timedelta):  # MySQLdb returns timedeltas instead of times
            total_seconds = val.days * (24 * 60 * 60) + val.seconds
            if 0 <= total_seconds <= 24 * 60 * 60:
                minutes, seconds = divmod(total_seconds, 60)
                hours, minutes = divmod(minutes, 60)
                return time(hours, minutes, seconds, val.microseconds)
        elif not isinstance(val, time): throw(ValueError,
            'Value of unexpected type received from database%s: instead of time or timedelta got %s'
            % ('for attribute %s' % converter.attr if converter.attr else '', type(val)))
        return val

class MySQLTimedeltaConverter(dbapiprovider.TimedeltaConverter):
    sql_type_name = 'TIME'

class MySQLUuidConverter(dbapiprovider.UuidConverter):
    def sql_type(converter):
        return 'BINARY(16)'

class MySQLProvider(DBAPIProvider):
    dialect = 'MySQL'
    paramstyle = 'format'
    quote_char = "`"
    max_name_len = 64
    table_if_not_exists_syntax = True
    index_if_not_exists_syntax = False
    select_for_update_nowait_syntax = False
    max_time_precision = default_time_precision = 0
    varchar_default_max_len = 255

    dbapi_module = mysql_module
    dbschema_cls = MySQLSchema
    translator_cls = MySQLTranslator
    sqlbuilder_cls = MySQLBuilder

    fk_types = { 'SERIAL' : 'BIGINT UNSIGNED' }

    converter_classes = [
        (bool, dbapiprovider.BoolConverter),
        (basestring, MySQLStrConverter),
        (int, dbapiprovider.IntConverter),
        (float, MySQLRealConverter),
        (Decimal, dbapiprovider.DecimalConverter),
        (datetime, dbapiprovider.DatetimeConverter),
        (date, dbapiprovider.DateConverter),
        (time, MySQLTimeConverter),
        (timedelta, MySQLTimedeltaConverter),
        (UUID, MySQLUuidConverter),
        (buffer, MySQLBlobConverter),
    ]
    if PY2:
        converter_classes += [
            (long, MySQLLongConverter),
        ]

    def normalize_name(provider, name):
        return name[:provider.max_name_len].lower()

    @wrap_dbapi_exceptions
    def inspect_connection(provider, connection):
        cursor = connection.cursor()
        cursor.execute('select version()')
        row = cursor.fetchone()
        assert row is not None
        provider.server_version = get_version_tuple(row[0])
        if provider.server_version >= (5, 6, 4):
            provider.max_time_precision = 6
        cursor.execute('select database()')
        provider.default_schema_name = cursor.fetchone()[0]

    def should_reconnect(provider, exc):
        return isinstance(exc, mysql_module.OperationalError) and exc.args[0] == 2006

    def get_pool(provider, *args, **kwargs):
        if 'conv' not in kwargs:
            conv = mysql_converters.conversions.copy()
            if mysql_module_name == 'MySQLdb':
                conv[FIELD_TYPE.BLOB] = [(FLAG.BINARY, buffer)]
                conv[timedelta] = lambda td, c: string_literal(timedelta2str(td), c)
            conv[FIELD_TYPE.TIMESTAMP] = str2datetime
            conv[FIELD_TYPE.DATETIME] = str2datetime
            conv[FIELD_TYPE.TIME] = str2timedelta
            kwargs['conv'] = conv
        if 'charset' not in kwargs:
            kwargs['charset'] = 'utf8'
        kwargs['client_flag'] = kwargs.get('client_flag', 0) | CLIENT.FOUND_ROWS
        return Pool(mysql_module, *args, **kwargs)

    @wrap_dbapi_exceptions
    def set_transaction_mode(provider, connection, cache):
        assert not cache.in_transaction
        db_session = cache.db_session
        if db_session is not None and db_session.ddl:
            cursor = connection.cursor()
            cursor.execute("SHOW VARIABLES LIKE 'foreign_key_checks'")
            fk = cursor.fetchone()
            if fk is not None: fk = (fk[1] == 'ON')
            if fk:
                sql = 'SET foreign_key_checks = 0'
                if core.debug: log_orm(sql)
                cursor.execute(sql)
            cache.saved_fk_state = bool(fk)
            cache.in_transaction = True
        cache.immediate = True
        if db_session is not None and db_session.serializable:
            cursor = connection.cursor()
            sql = 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'
            if core.debug: log_orm(sql)
            cursor.execute(sql)
            cache.in_transaction = True

    @wrap_dbapi_exceptions
    def release(provider, connection, cache=None):
        if cache is not None:
            db_session = cache.db_session
            if db_session is not None and db_session.ddl and cache.saved_fk_state:
                try:
                    cursor = connection.cursor()
                    sql = 'SET foreign_key_checks = 1'
                    if core.debug: log_orm(sql)
                    cursor.execute(sql)
                except:
                    provider.pool.drop(connection)
                    raise
        DBAPIProvider.release(provider, connection, cache)

    def table_exists(provider, connection, table_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        cursor = connection.cursor()
        if case_sensitive: sql = 'SELECT table_name FROM information_schema.tables ' \
                                 'WHERE table_schema=%s and table_name=%s'
        else: sql = 'SELECT table_name FROM information_schema.tables ' \
                    'WHERE table_schema=%s and UPPER(table_name)=UPPER(%s)'
        cursor.execute(sql, [ db_name, table_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

    def index_exists(provider, connection, table_name, index_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        if case_sensitive: sql = 'SELECT index_name FROM information_schema.statistics ' \
                                 'WHERE table_schema=%s and table_name=%s and index_name=%s'
        else: sql = 'SELECT index_name FROM information_schema.statistics ' \
                    'WHERE table_schema=%s and table_name=%s and UPPER(index_name)=UPPER(%s)'
        cursor = connection.cursor()
        cursor.execute(sql, [ db_name, table_name, index_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

    def fk_exists(provider, connection, table_name, fk_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        if case_sensitive: sql = 'SELECT constraint_name FROM information_schema.table_constraints ' \
                                 'WHERE table_schema=%s and table_name=%s ' \
                                 "and constraint_type='FOREIGN KEY' and constraint_name=%s"
        else: sql = 'SELECT constraint_name FROM information_schema.table_constraints ' \
                    'WHERE table_schema=%s and table_name=%s ' \
                    "and constraint_type='FOREIGN KEY' and UPPER(constraint_name)=UPPER(%s)"
        cursor = connection.cursor()
        cursor.execute(sql, [ db_name, table_name, fk_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

provider_cls = MySQLProvider

def str2datetime(s):
    if 19 < len(s) < 26: s += '000000'[:26-len(s)]
    s = s.replace('-', ' ').replace(':', ' ').replace('.', ' ').replace('T', ' ')
    return datetime(*imap(int, s.split()))
<commit_msg>Refactor import from MySQLdb for conformity<commit_after>from __future__ import absolute_import
from pony.py23compat import PY2, imap, basestring, buffer

from decimal import Decimal, InvalidOperation
from datetime import datetime, date, time, timedelta
from uuid import UUID

import warnings
warnings.filterwarnings('ignore', '^Table.+already exists$', Warning, '^pony\\.orm\\.dbapiprovider$')

try:
    import MySQLdb as mysql_module
except ImportError as e:
    try:
        import pymysql as mysql_module
    except ImportError:
        raise ImportError('No module named MySQLdb or pymysql found')
    else:
        import pymysql.converters as mysql_converters
        from pymysql.constants import FIELD_TYPE, FLAG, CLIENT
        if PY2:
            mysql_converters.encoders[buffer] = lambda val: mysql_converters.escape_str(str(val))
        mysql_converters.encoders[timedelta] = lambda val: mysql_converters.escape_str(timedelta2str(val))
        mysql_module_name = 'pymysql'
else:
    import MySQLdb.converters as mysql_converters
    from MySQLdb.constants import FIELD_TYPE, FLAG, CLIENT
    mysql_module_name = 'MySQLdb'
    from MySQLdb import string_literal

from pony.orm import core, dbschema, dbapiprovider
from pony.orm.core import log_orm, log_sql, OperationalError
from pony.orm.dbapiprovider import DBAPIProvider, Pool, get_version_tuple, wrap_dbapi_exceptions
from pony.orm.sqltranslation import SQLTranslator
from pony.orm.sqlbuilding import SQLBuilder, join
from pony.utils import throw
from pony.converting import str2timedelta, timedelta2str

class MySQLColumn(dbschema.Column):
    auto_template = '%(type)s PRIMARY KEY AUTO_INCREMENT'

class MySQLSchema(dbschema.DBSchema):
    dialect = 'MySQL'
    inline_fk_syntax = False
    column_class = MySQLColumn

class MySQLTranslator(SQLTranslator):
    dialect = 'MySQL'

class MySQLBuilder(SQLBuilder):
    dialect = 'MySQL'
    def CONCAT(builder, *args):
        return 'concat(',  join(', ', imap(builder, args)), ')'
    def TRIM(builder, expr, chars=None):
        if chars is None: return 'trim(', builder(expr), ')'
        return 'trim(both ', builder(chars), ' from ' ,builder(expr), ')'
    def LTRIM(builder, expr, chars=None):
        if chars is None: return 'ltrim(', builder(expr), ')'
        return 'trim(leading ', builder(chars), ' from ' ,builder(expr), ')'
    def RTRIM(builder, expr, chars=None):
        if chars is None: return 'rtrim(', builder(expr), ')'
        return 'trim(trailing ', builder(chars), ' from ' ,builder(expr), ')'
    def YEAR(builder, expr):
        return 'year(', builder(expr), ')'
    def MONTH(builder, expr):
        return 'month(', builder(expr), ')'
    def DAY(builder, expr):
        return 'day(', builder(expr), ')'
    def HOUR(builder, expr):
        return 'hour(', builder(expr), ')'
    def MINUTE(builder, expr):
        return 'minute(', builder(expr), ')'
    def SECOND(builder, expr):
        return 'second(', builder(expr), ')'
    def DATE_ADD(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_ADD(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'ADDTIME(', builder(expr), ', ', builder(delta), ')'
    def DATE_SUB(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_SUB(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'SUBTIME(', builder(expr), ', ', builder(delta), ')'
    def DATETIME_ADD(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_ADD(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'ADDTIME(', builder(expr), ', ', builder(delta), ')'
    def DATETIME_SUB(builder, expr, delta):
        if isinstance(delta, timedelta):
            return 'DATE_SUB(', builder(expr), ", INTERVAL '", timedelta2str(delta), "' HOUR_SECOND)"
        return 'SUBTIME(', builder(expr), ', ', builder(delta), ')'

class MySQLStrConverter(dbapiprovider.StrConverter):
    def sql_type(converter):
        result = 'VARCHAR(%d)' % converter.max_len if converter.max_len else 'LONGTEXT'
        if converter.db_encoding: result += ' CHARACTER SET %s' % converter.db_encoding
        return result

if PY2:
    class MySQLLongConverter(dbapiprovider.IntConverter):
        def sql_type(converter):
            return 'BIGINT'

class MySQLRealConverter(dbapiprovider.RealConverter):
    def sql_type(converter):
        return 'DOUBLE'

class MySQLBlobConverter(dbapiprovider.BlobConverter):
    def sql_type(converter):
        return 'LONGBLOB'

class MySQLTimeConverter(dbapiprovider.TimeConverter):
    def sql2py(converter, val):
        if isinstance(val, timedelta):  # MySQLdb returns timedeltas instead of times
            total_seconds = val.days * (24 * 60 * 60) + val.seconds
            if 0 <= total_seconds <= 24 * 60 * 60:
                minutes, seconds = divmod(total_seconds, 60)
                hours, minutes = divmod(minutes, 60)
                return time(hours, minutes, seconds, val.microseconds)
        elif not isinstance(val, time): throw(ValueError,
            'Value of unexpected type received from database%s: instead of time or timedelta got %s'
            % ('for attribute %s' % converter.attr if converter.attr else '', type(val)))
        return val

class MySQLTimedeltaConverter(dbapiprovider.TimedeltaConverter):
    sql_type_name = 'TIME'

class MySQLUuidConverter(dbapiprovider.UuidConverter):
    def sql_type(converter):
        return 'BINARY(16)'

class MySQLProvider(DBAPIProvider):
    dialect = 'MySQL'
    paramstyle = 'format'
    quote_char = "`"
    max_name_len = 64
    table_if_not_exists_syntax = True
    index_if_not_exists_syntax = False
    select_for_update_nowait_syntax = False
    max_time_precision = default_time_precision = 0
    varchar_default_max_len = 255

    dbapi_module = mysql_module
    dbschema_cls = MySQLSchema
    translator_cls = MySQLTranslator
    sqlbuilder_cls = MySQLBuilder

    fk_types = { 'SERIAL' : 'BIGINT UNSIGNED' }

    converter_classes = [
        (bool, dbapiprovider.BoolConverter),
        (basestring, MySQLStrConverter),
        (int, dbapiprovider.IntConverter),
        (float, MySQLRealConverter),
        (Decimal, dbapiprovider.DecimalConverter),
        (datetime, dbapiprovider.DatetimeConverter),
        (date, dbapiprovider.DateConverter),
        (time, MySQLTimeConverter),
        (timedelta, MySQLTimedeltaConverter),
        (UUID, MySQLUuidConverter),
        (buffer, MySQLBlobConverter),
    ]
    if PY2:
        converter_classes += [
            (long, MySQLLongConverter),
        ]

    def normalize_name(provider, name):
        return name[:provider.max_name_len].lower()

    @wrap_dbapi_exceptions
    def inspect_connection(provider, connection):
        cursor = connection.cursor()
        cursor.execute('select version()')
        row = cursor.fetchone()
        assert row is not None
        provider.server_version = get_version_tuple(row[0])
        if provider.server_version >= (5, 6, 4):
            provider.max_time_precision = 6
        cursor.execute('select database()')
        provider.default_schema_name = cursor.fetchone()[0]

    def should_reconnect(provider, exc):
        return isinstance(exc, mysql_module.OperationalError) and exc.args[0] == 2006

    def get_pool(provider, *args, **kwargs):
        if 'conv' not in kwargs:
            conv = mysql_converters.conversions.copy()
            if mysql_module_name == 'MySQLdb':
                conv[FIELD_TYPE.BLOB] = [(FLAG.BINARY, buffer)]
                conv[timedelta] = lambda td, c: string_literal(timedelta2str(td), c)
            conv[FIELD_TYPE.TIMESTAMP] = str2datetime
            conv[FIELD_TYPE.DATETIME] = str2datetime
            conv[FIELD_TYPE.TIME] = str2timedelta
            kwargs['conv'] = conv
        if 'charset' not in kwargs:
            kwargs['charset'] = 'utf8'
        kwargs['client_flag'] = kwargs.get('client_flag', 0) | CLIENT.FOUND_ROWS
        return Pool(mysql_module, *args, **kwargs)

    @wrap_dbapi_exceptions
    def set_transaction_mode(provider, connection, cache):
        assert not cache.in_transaction
        db_session = cache.db_session
        if db_session is not None and db_session.ddl:
            cursor = connection.cursor()
            cursor.execute("SHOW VARIABLES LIKE 'foreign_key_checks'")
            fk = cursor.fetchone()
            if fk is not None: fk = (fk[1] == 'ON')
            if fk:
                sql = 'SET foreign_key_checks = 0'
                if core.debug: log_orm(sql)
                cursor.execute(sql)
            cache.saved_fk_state = bool(fk)
            cache.in_transaction = True
        cache.immediate = True
        if db_session is not None and db_session.serializable:
            cursor = connection.cursor()
            sql = 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'
            if core.debug: log_orm(sql)
            cursor.execute(sql)
            cache.in_transaction = True

    @wrap_dbapi_exceptions
    def release(provider, connection, cache=None):
        if cache is not None:
            db_session = cache.db_session
            if db_session is not None and db_session.ddl and cache.saved_fk_state:
                try:
                    cursor = connection.cursor()
                    sql = 'SET foreign_key_checks = 1'
                    if core.debug: log_orm(sql)
                    cursor.execute(sql)
                except:
                    provider.pool.drop(connection)
                    raise
        DBAPIProvider.release(provider, connection, cache)

    def table_exists(provider, connection, table_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        cursor = connection.cursor()
        if case_sensitive: sql = 'SELECT table_name FROM information_schema.tables ' \
                                 'WHERE table_schema=%s and table_name=%s'
        else: sql = 'SELECT table_name FROM information_schema.tables ' \
                    'WHERE table_schema=%s and UPPER(table_name)=UPPER(%s)'
        cursor.execute(sql, [ db_name, table_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

    def index_exists(provider, connection, table_name, index_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        if case_sensitive: sql = 'SELECT index_name FROM information_schema.statistics ' \
                                 'WHERE table_schema=%s and table_name=%s and index_name=%s'
        else: sql = 'SELECT index_name FROM information_schema.statistics ' \
                    'WHERE table_schema=%s and table_name=%s and UPPER(index_name)=UPPER(%s)'
        cursor = connection.cursor()
        cursor.execute(sql, [ db_name, table_name, index_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

    def fk_exists(provider, connection, table_name, fk_name, case_sensitive=True):
        db_name, table_name = provider.split_table_name(table_name)
        if case_sensitive: sql = 'SELECT constraint_name FROM information_schema.table_constraints ' \
                                 'WHERE table_schema=%s and table_name=%s ' \
                                 "and constraint_type='FOREIGN KEY' and constraint_name=%s"
        else: sql = 'SELECT constraint_name FROM information_schema.table_constraints ' \
                    'WHERE table_schema=%s and table_name=%s ' \
                    "and constraint_type='FOREIGN KEY' and UPPER(constraint_name)=UPPER(%s)"
        cursor = connection.cursor()
        cursor.execute(sql, [ db_name, table_name, fk_name ])
        row = cursor.fetchone()
        return row[0] if row is not None else None

provider_cls = MySQLProvider

def str2datetime(s):
    if 19 < len(s) < 26: s += '000000'[:26-len(s)]
    s = s.replace('-', ' ').replace(':', ' ').replace('.', ' ').replace('T', ' ')
    return datetime(*imap(int, s.split()))
<|endoftext|>


<commit_before>{
  'variables': {
    'node_shared_openssl%': 'true'
  },
  'targets': [
    {
      'target_name': 'KeyModule',
      'sources': [
        'src/eckey.cc'
      ],
      'conditions': [
        ['node_shared_openssl=="false"', {
          # so when "node_shared_openssl" is "false", then OpenSSL has been
          # bundled into the node executable. So we need to include the same
          # header files that were used when building node.
          'include_dirs': [
            '<(node_root_dir)/deps/openssl/openssl/include'
          ],
          "conditions" : [
            ["target_arch=='ia32'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ]
            }],
            ["target_arch=='x64'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ]
            }],
            ["target_arch=='arm'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ]
            }]
          ]
        }]
      ]
    }
  ]
}

<commit_msg>Specify OpenSSL lib path so that bitcore references to OpenSSL will link to separate OpenSSL DLL in Windows (following bignum@1.6 pattern). Fixes issue #106<commit_after>{
  'variables': {
    'node_shared_openssl%': 'true'
  },
  'targets': [
    {
      'target_name': 'KeyModule',
      'sources': [
        'src/eckey.cc'
      ],
      'conditions': [
        # For Windows, require either a 32-bit or 64-bit
        # separately-compiled OpenSSL library.
	# Currently set up to use with the following OpenSSL distro:
	#
	# http://slproweb.com/products/Win32OpenSSL.html
        [
	  'OS=="win"',
	  {
            'conditions':
	    [
              [
	        'target_arch=="x64"',
	        {
	          'variables': {
                    'openssl_root%': 'C:/OpenSSL-Win64'
                  },
                }, {
                 'variables': {
                   'openssl_root%': 'C:/OpenSSL-Win32'
                  }
		}
	      ]
            ],
            'libraries': [
              '-l<(openssl_root)/lib/libeay32.lib',
            ],
            'include_dirs': [
              '<(openssl_root)/include',
            ],
          },

          # Otherwise, if not Windows, link against the exposed OpenSSL
	  # in Node.
          {
          "conditions": [
        ['node_shared_openssl=="false"', {
          # so when "node_shared_openssl" is "false", then OpenSSL has been
          # bundled into the node executable. So we need to include the same
          # header files that were used when building node.
          'include_dirs': [
            '<(node_root_dir)/deps/openssl/openssl/include'
          ],
          "conditions" : [
            ["target_arch=='ia32'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ]
            }],
            ["target_arch=='x64'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ]
            }],
            ["target_arch=='arm'", {
              "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ]
            }]
          ]
        }]
        ]}
      ]]
    }
  ]
}

<|endoftext|>