<commit_before># -*- coding: utf-8 -*-
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2009 Benjamin Schindler <bschindler@inf.ethz.ch>
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Pretty printers for Eigen::Matrix
# This is still pretty basic as the python extension to gdb is still pretty basic.
# It cannot handle complex eigen types and it doesn't support any of the other eigen types
# Such as quaternion or some other type.
# This code supports fixed size as well as dynamic size matrices

# To use it:
#
# * Create a directory and put the file as well as an empty __init__.py in
#   that directory.
# * Create a ~/.gdbinit file, that contains the following:
#      python
#      import sys
#      sys.path.insert(0, '/path/to/eigen/printer/directory')
#      from printers import register_eigen_printers
#      register_eigen_printers (None)
#      end

import gdb
import re
import itertools

class EigenMatrixPrinter:
	"Print Eigen Matrix or Array of some kind"

	def __init__(self, variety, val):
		"Extract all the necessary information"

		# Save the variety (presumably "Matrix" or "Array") for later usage
		self.variety = variety

		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		tag = self.type.tag
		regex = re.compile('\<.*\>')
		m = regex.findall(tag)[0][1:-1]
		template_params = m.split(',')
		template_params = map(lambda x:x.replace(" ", ""), template_params)

		if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001':
			self.rows = val['m_storage']['m_rows']
		else:
			self.rows = int(template_params[1])

		if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001':
			self.cols = val['m_storage']['m_cols']
		else:
			self.cols = int(template_params[2])

		self.options = 0 # default value
		if len(template_params) > 3:
			self.options = template_params[3];

		self.rowMajor = (int(self.options) & 0x1)

		self.innerType = self.type.template_argument(0)

		self.val = val

		# Fixed size matrices have a struct as their storage, so we need to walk through this
		self.data = self.val['m_storage']['m_data']
		if self.data.type.code == gdb.TYPE_CODE_STRUCT:
			self.data = self.data['array']
			self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, rows, cols, dataPtr, rowMajor):
			self.rows = rows
			self.cols = cols
			self.dataPtr = dataPtr
			self.currentRow = 0
			self.currentCol = 0
			self.rowMajor = rowMajor

		def __iter__ (self):
			return self

		def next(self):

			row = self.currentRow
			col = self.currentCol
			if self.rowMajor == 0:
				if self.currentCol >= self.cols:
					raise StopIteration

				self.currentRow = self.currentRow + 1
				if self.currentRow >= self.rows:
					self.currentRow = 0
					self.currentCol = self.currentCol + 1
			else:
				if self.currentRow >= self.rows:
					raise StopIteration

				self.currentCol = self.currentCol + 1
				if self.currentCol >= self.cols:
					self.currentCol = 0
					self.currentRow = self.currentRow + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			if (self.cols == 1): #if it's a column vector
				return ('[%d]' % (row,), item)
			elif (self.rows == 1): #if it's a row vector
				return ('[%d]' % (col,), item)
			return ('[%d,%d]' % (row, col), item)

	def children(self):

		return self._iterator(self.rows, self.cols, self.data, self.rowMajor)

	def to_string(self):
		return "Eigen::%s<%s,%d,%d,%s> (data ptr: %s)" % (self.variety, self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else  "ColMajor", self.data)

class EigenQuaternionPrinter:
	"Print an Eigen Quaternion"

	def __init__(self, val):
		"Extract all the necessary information"
		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		self.innerType = self.type.template_argument(0)
		self.val = val

		# Quaternions have a struct as their storage, so we need to walk through this
		self.data = self.val['m_coeffs']['m_storage']['m_data']['array']
		self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, dataPtr):
			self.dataPtr = dataPtr
			self.currentElement = 0
			self.elementNames = ['x', 'y', 'z', 'w']

		def __iter__ (self):
			return self

		def next(self):
			element = self.currentElement

			if self.currentElement >= 4: #there are 4 elements in a quanternion
				raise StopIteration

			self.currentElement = self.currentElement + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			return ('[%s]' % (self.elementNames[element],), item)

	def children(self):

		return self._iterator(self.data)

	def to_string(self):
		return "Eigen::Quaternion<%s> (data ptr: %s)" % (self.innerType, self.data)

def build_eigen_dictionary ():
	pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val)
	pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter("Matrix", val)
	pretty_printers_dict[re.compile('^Eigen::Array<.*>$')]  = lambda val: EigenMatrixPrinter("Array",  val)

def register_eigen_printers(obj):
	"Register eigen pretty-printers with objfile Obj"

	if obj == None:
		obj = gdb
	obj.pretty_printers.append(lookup_function)

def lookup_function(val):
	"Look-up and return a pretty-printer that can print va."

	type = val.type

	if type.code == gdb.TYPE_CODE_REF:
		type = type.target()

	type = type.unqualified().strip_typedefs()

	typename = type.tag
	if typename == None:
		return None

	for function in pretty_printers_dict:
		if function.search(typename):
			return pretty_printers_dict[function](val)

	return None

pretty_printers_dict = {}

build_eigen_dictionary ()
<commit_msg>fix bug 511: pretty printers on windows<commit_after># -*- coding: utf-8 -*-
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2009 Benjamin Schindler <bschindler@inf.ethz.ch>
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Pretty printers for Eigen::Matrix
# This is still pretty basic as the python extension to gdb is still pretty basic.
# It cannot handle complex eigen types and it doesn't support any of the other eigen types
# Such as quaternion or some other type.
# This code supports fixed size as well as dynamic size matrices

# To use it:
#
# * Create a directory and put the file as well as an empty __init__.py in
#   that directory.
# * Create a ~/.gdbinit file, that contains the following:
#      python
#      import sys
#      sys.path.insert(0, '/path/to/eigen/printer/directory')
#      from printers import register_eigen_printers
#      register_eigen_printers (None)
#      end

import gdb
import re
import itertools

class EigenMatrixPrinter:
	"Print Eigen Matrix or Array of some kind"

	def __init__(self, variety, val):
		"Extract all the necessary information"

		# Save the variety (presumably "Matrix" or "Array") for later usage
		self.variety = variety

		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		tag = self.type.tag
		regex = re.compile('\<.*\>')
		m = regex.findall(tag)[0][1:-1]
		template_params = m.split(',')
		template_params = map(lambda x:x.replace(" ", ""), template_params)

		if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001' or template_params[1] == '-1':
			self.rows = val['m_storage']['m_rows']
		else:
			self.rows = int(template_params[1])

		if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001' or template_params[2] == '-1':
			self.cols = val['m_storage']['m_cols']
		else:
			self.cols = int(template_params[2])

		self.options = 0 # default value
		if len(template_params) > 3:
			self.options = template_params[3];

		self.rowMajor = (int(self.options) & 0x1)

		self.innerType = self.type.template_argument(0)

		self.val = val

		# Fixed size matrices have a struct as their storage, so we need to walk through this
		self.data = self.val['m_storage']['m_data']
		if self.data.type.code == gdb.TYPE_CODE_STRUCT:
			self.data = self.data['array']
			self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, rows, cols, dataPtr, rowMajor):
			self.rows = rows
			self.cols = cols
			self.dataPtr = dataPtr
			self.currentRow = 0
			self.currentCol = 0
			self.rowMajor = rowMajor

		def __iter__ (self):
			return self

		def next(self):

			row = self.currentRow
			col = self.currentCol
			if self.rowMajor == 0:
				if self.currentCol >= self.cols:
					raise StopIteration

				self.currentRow = self.currentRow + 1
				if self.currentRow >= self.rows:
					self.currentRow = 0
					self.currentCol = self.currentCol + 1
			else:
				if self.currentRow >= self.rows:
					raise StopIteration

				self.currentCol = self.currentCol + 1
				if self.currentCol >= self.cols:
					self.currentCol = 0
					self.currentRow = self.currentRow + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			if (self.cols == 1): #if it's a column vector
				return ('[%d]' % (row,), item)
			elif (self.rows == 1): #if it's a row vector
				return ('[%d]' % (col,), item)
			return ('[%d,%d]' % (row, col), item)

	def children(self):

		return self._iterator(self.rows, self.cols, self.data, self.rowMajor)

	def to_string(self):
		return "Eigen::%s<%s,%d,%d,%s> (data ptr: %s)" % (self.variety, self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else  "ColMajor", self.data)

class EigenQuaternionPrinter:
	"Print an Eigen Quaternion"

	def __init__(self, val):
		"Extract all the necessary information"
		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		self.innerType = self.type.template_argument(0)
		self.val = val

		# Quaternions have a struct as their storage, so we need to walk through this
		self.data = self.val['m_coeffs']['m_storage']['m_data']['array']
		self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, dataPtr):
			self.dataPtr = dataPtr
			self.currentElement = 0
			self.elementNames = ['x', 'y', 'z', 'w']

		def __iter__ (self):
			return self

		def next(self):
			element = self.currentElement

			if self.currentElement >= 4: #there are 4 elements in a quanternion
				raise StopIteration

			self.currentElement = self.currentElement + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			return ('[%s]' % (self.elementNames[element],), item)

	def children(self):

		return self._iterator(self.data)

	def to_string(self):
		return "Eigen::Quaternion<%s> (data ptr: %s)" % (self.innerType, self.data)

def build_eigen_dictionary ():
	pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val)
	pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter("Matrix", val)
	pretty_printers_dict[re.compile('^Eigen::Array<.*>$')]  = lambda val: EigenMatrixPrinter("Array",  val)

def register_eigen_printers(obj):
	"Register eigen pretty-printers with objfile Obj"

	if obj == None:
		obj = gdb
	obj.pretty_printers.append(lookup_function)

def lookup_function(val):
	"Look-up and return a pretty-printer that can print va."

	type = val.type

	if type.code == gdb.TYPE_CODE_REF:
		type = type.target()

	type = type.unqualified().strip_typedefs()

	typename = type.tag
	if typename == None:
		return None

	for function in pretty_printers_dict:
		if function.search(typename):
			return pretty_printers_dict[function](val)

	return None

pretty_printers_dict = {}

build_eigen_dictionary ()
<|endoftext|>


<commit_before>from pprint import pprint

from paver.easy import task, needs, path, sh, cmdopts, options
from paver.setuputils import setup

import os
import sys

# add the current directory as the first listing on the python path
# so that we import the correct version.py
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
import version

DEFAULT_ARDUINO_BOARDS = ['mega2560']

setup(name='wheeler.dmf-control-board-firmware',
      version=version.getVersion(),
      description='Arduino-based dmf_control_board firmware and Python API.',
      author='Ryan Fobel',
      author_email='ryan@fobel.net',
      url='http://microfluidics.utoronto.ca/git/dmf-control-board.git',
      license='GPLv2',
      packages=['dmf_control_board_firmware'],
      include_package_data=True,
      install_requires=['arduino_helpers', 'decorator', 'functools32',
                        'pyserial'])

@task
def create_config():
    sketch_directory = path('dmf_control_board_firmware').joinpath('src',
                                                          'dmf_control_board')
    sketch_directory.joinpath('Config.h.skeleton').copy(sketch_directory
                                                        .joinpath('Config.h'))

@task
@needs('create_config')
@cmdopts([('sconsflags=', 'f', 'Flags to pass to SCons.'),
          ('boards=', 'b', 'Comma-separated list of board names to compile '
           'for (e.g., `mega2560`).')])
def build_firmware():
    scons_flags = getattr(options, 'sconsflags', '')
    boards = [b.strip() for b in getattr(options, 'boards', '').split(',')
              if b.strip()]
    if not boards:
        boards = DEFAULT_ARDUINO_BOARDS
    for board in boards:
        # Compile firmware once for each specified board.
        sh('scons %s ARDUINO_BOARD="%s"' % (scons_flags, board))

@task
@needs('generate_setup', 'minilib', 'build_firmware',
       'setuptools.command.sdist')
def sdist():
    """Overrides sdist to make sure that our setup.py is generated."""
    pass
<commit_msg>Add requirement for arduino_helpers>=0.3.post4<commit_after>from pprint import pprint

from paver.easy import task, needs, path, sh, cmdopts, options
from paver.setuputils import setup

import os
import sys

# add the current directory as the first listing on the python path
# so that we import the correct version.py
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
import version

DEFAULT_ARDUINO_BOARDS = ['mega2560']

setup(name='wheeler.dmf-control-board-firmware',
      version=version.getVersion(),
      description='Arduino-based dmf_control_board firmware and Python API.',
      author='Ryan Fobel',
      author_email='ryan@fobel.net',
      url='http://microfluidics.utoronto.ca/git/dmf-control-board.git',
      license='GPLv2',
      packages=['dmf_control_board_firmware'],
      include_package_data=True,
      install_requires=['arduino_helpers>=0.3.post4', 'decorator', 'functools32',
                        'pyserial'])

@task
def create_config():
    sketch_directory = path('dmf_control_board_firmware').joinpath('src',
                                                          'dmf_control_board')
    sketch_directory.joinpath('Config.h.skeleton').copy(sketch_directory
                                                        .joinpath('Config.h'))

@task
@needs('create_config')
@cmdopts([('sconsflags=', 'f', 'Flags to pass to SCons.'),
          ('boards=', 'b', 'Comma-separated list of board names to compile '
           'for (e.g., `mega2560`).')])
def build_firmware():
    scons_flags = getattr(options, 'sconsflags', '')
    boards = [b.strip() for b in getattr(options, 'boards', '').split(',')
              if b.strip()]
    if not boards:
        boards = DEFAULT_ARDUINO_BOARDS
    for board in boards:
        # Compile firmware once for each specified board.
        sh('scons %s ARDUINO_BOARD="%s"' % (scons_flags, board))

@task
@needs('generate_setup', 'minilib', 'build_firmware',
       'setuptools.command.sdist')
def sdist():
    """Overrides sdist to make sure that our setup.py is generated."""
    pass
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2009 Benjamin Schindler <bschindler@inf.ethz.ch>
#
# Eigen is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# Alternatively, you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# Eigen 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 Lesser General Public License or the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License and a copy of the GNU General Public License along with
# Eigen. If not, see <http://www.gnu.org/licenses/>.

# Pretty printers for Eigen::Matrix
# This is still pretty basic as the python extension to gdb is still pretty basic.
# It cannot handle complex eigen types and it doesn't support any of the other eigen types
# Such as quaternion or some other type.
# This code supports fixed size as well as dynamic size matrices

# To use it:
#
# * create a directory and put the file as well as an empty __init__.py in that directory
# * Create a ~/.gdbinit file, that contains the following:

import gdb
import re
import itertools

class EigenMatrixPrinter:
	"Print Eigen Matrix of some kind"

	def __init__(self, val):
		"Extract all the necessary information"
		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		tag = self.type.tag
		regex = re.compile('\<.*\>')
		m = regex.findall(tag)[0][1:-1]
		template_params = m.split(',')
		template_params = map(lambda x:x.replace(" ", ""), template_params)

		self.rows = int(template_params[1])
		self.cols = int(template_params[2])
		self.options = 0 # default value
		if len(template_params) > 3:
			self.options = template_params[3];

		self.rowMajor = (int(self.options) & 0x1)

		if self.rows == 10000:
			self.rows = val['m_storage']['m_rows']

		if self.cols == 10000:
			self.cols = val['m_storage']['m_cols']

		self.innerType = self.type.template_argument(0)

		self.val = val

		# Fixed size matrices have a struct as their storage, so we need to walk through this
		self.data = self.val['m_storage']['m_data']
		if self.data.type.code == gdb.TYPE_CODE_STRUCT:
			self.data = self.data['array']
			self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, rows, cols, dataPtr, rowMajor):
			self.rows = rows
			self.cols = cols
			self.dataPtr = dataPtr
			self.currentRow = 0
			self.currentCol = 0
			self.rowMajor = rowMajor

		def __iter__ (self):
			return self

		def next(self):

			row = self.currentRow
			col = self.currentCol
			if self.rowMajor == 0:
				if self.currentCol >= self.cols:
					raise StopIteration

				self.currentRow = self.currentRow + 1
				if self.currentRow >= self.rows:
					self.currentRow = 0
					self.currentCol = self.currentCol + 1
			else:
				if self.currentRow >= self.rows:
					raise StopIteration

				self.currentCol = self.currentCol + 1
				if self.currentCol >= self.cols:
					self.currentCol = 0
					self.currentRow = self.currentRow + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1

			return ('[%d, %d]' % (row, col), item)

	def children(self):

		return self._iterator(self.rows, self.cols, self.data, self.rowMajor)

	def to_string(self):
		return "Eigen::Matrix<%s,%d,%d,%s> (data ptr: %s)" % (self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else  "ColMajor", self.data)

def build_eigen_dictionary ():
	pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter(val)

def register_eigen_printers(obj):
	"Register eigen pretty-printers with objfile Obj"

	if obj == None:
		obj = gdb
	obj.pretty_printers.append(lookup_function)

def lookup_function(val):
	"Look-up and return a pretty-printer that can print va."

	type = val.type

	if type.code == gdb.TYPE_CODE_REF:
		type = type.target()

	type = type.unqualified().strip_typedefs()

	typename = type.tag
	if typename == None:
		return None

	for function in pretty_printers_dict:
		if function.search(typename):
			return pretty_printers_dict[function](val)

	return None

pretty_printers_dict = {}

build_eigen_dictionary ()
<commit_msg>Changed the gdb display format of vectors and added support for quaternions.<commit_after># -*- coding: utf-8 -*-
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2009 Benjamin Schindler <bschindler@inf.ethz.ch>
#
# Eigen is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# Alternatively, you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# Eigen 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 Lesser General Public License or the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License and a copy of the GNU General Public License along with
# Eigen. If not, see <http://www.gnu.org/licenses/>.

# Pretty printers for Eigen::Matrix
# This is still pretty basic as the python extension to gdb is still pretty basic.
# It cannot handle complex eigen types and it doesn't support any of the other eigen types
# Such as quaternion or some other type.
# This code supports fixed size as well as dynamic size matrices

# To use it:
#
# * create a directory and put the file as well as an empty __init__.py in that directory
# * Create a ~/.gdbinit file, that contains the following:

import gdb
import re
import itertools

class EigenMatrixPrinter:
	"Print Eigen Matrix of some kind"

	def __init__(self, val):
		"Extract all the necessary information"
		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		tag = self.type.tag
		regex = re.compile('\<.*\>')
		m = regex.findall(tag)[0][1:-1]
		template_params = m.split(',')
		template_params = map(lambda x:x.replace(" ", ""), template_params)

		self.rows = int(template_params[1])
		self.cols = int(template_params[2])
		self.options = 0 # default value
		if len(template_params) > 3:
			self.options = template_params[3];

		self.rowMajor = (int(self.options) & 0x1)

		if self.rows == 10000:
			self.rows = val['m_storage']['m_rows']

		if self.cols == 10000:
			self.cols = val['m_storage']['m_cols']

		self.innerType = self.type.template_argument(0)

		self.val = val

		# Fixed size matrices have a struct as their storage, so we need to walk through this
		self.data = self.val['m_storage']['m_data']
		if self.data.type.code == gdb.TYPE_CODE_STRUCT:
			self.data = self.data['array']
			self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, rows, cols, dataPtr, rowMajor):
			self.rows = rows
			self.cols = cols
			self.dataPtr = dataPtr
			self.currentRow = 0
			self.currentCol = 0
			self.rowMajor = rowMajor

		def __iter__ (self):
			return self

		def next(self):

			row = self.currentRow
			col = self.currentCol
			if self.rowMajor == 0:
				if self.currentCol >= self.cols:
					raise StopIteration

				self.currentRow = self.currentRow + 1
				if self.currentRow >= self.rows:
					self.currentRow = 0
					self.currentCol = self.currentCol + 1
			else:
				if self.currentRow >= self.rows:
					raise StopIteration

				self.currentCol = self.currentCol + 1
				if self.currentCol >= self.cols:
					self.currentCol = 0
					self.currentRow = self.currentRow + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			if (self.cols == 1): #if it's a column vector
				return ('[%d]' % (row,), item)
			elif (self.rows == 1): #if it's a row vector
				return ('[%d]' % (col,), item)
			return ('[%d,%d]' % (row, col), item)

	def children(self):

		return self._iterator(self.rows, self.cols, self.data, self.rowMajor)

	def to_string(self):
		return "Eigen::Matrix<%s,%d,%d,%s> (data ptr: %s)" % (self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else  "ColMajor", self.data)

class EigenQuaternionPrinter:
	"Print an Eigen Quaternion"

	def __init__(self, val):
		"Extract all the necessary information"
		# The gdb extension does not support value template arguments - need to extract them by hand
		type = val.type
		if type.code == gdb.TYPE_CODE_REF:
			type = type.target()
		self.type = type.unqualified().strip_typedefs()
		self.innerType = self.type.template_argument(0)
		self.val = val

		# Quaternions have a struct as their storage, so we need to walk through this
		self.data = self.val['m_coeffs']['m_storage']['m_data']['array']
		self.data = self.data.cast(self.innerType.pointer())

	class _iterator:
		def __init__ (self, dataPtr):
			self.dataPtr = dataPtr
			self.currentElement = 0
			self.elementNames = ['x', 'y', 'z', 'w']

		def __iter__ (self):
			return self

		def next(self):
			element = self.currentElement

			if self.currentElement >= 4: #there are 4 elements in a quanternion
				raise StopIteration

			self.currentElement = self.currentElement + 1

			item = self.dataPtr.dereference()
			self.dataPtr = self.dataPtr + 1
			return ('[%s]' % (self.elementNames[element],), item)

	def children(self):

		return self._iterator(self.data)

	def to_string(self):
		return "Eigen::Quaternion<%s> (data ptr: %s)" % (self.innerType, self.data)

def build_eigen_dictionary ():
	pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val)
	pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter(val)

def register_eigen_printers(obj):
	"Register eigen pretty-printers with objfile Obj"

	if obj == None:
		obj = gdb
	obj.pretty_printers.append(lookup_function)

def lookup_function(val):
	"Look-up and return a pretty-printer that can print va."

	type = val.type

	if type.code == gdb.TYPE_CODE_REF:
		type = type.target()

	type = type.unqualified().strip_typedefs()

	typename = type.tag
	if typename == None:
		return None

	for function in pretty_printers_dict:
		if function.search(typename):
			return pretty_printers_dict[function](val)

	return None

pretty_printers_dict = {}

build_eigen_dictionary ()
<|endoftext|>


<commit_before>"""
FlexGet build and development utilities - unfortunately this file is somewhat messy
"""
from __future__ import print_function
import glob
import os
import shutil
import sys

from paver.easy import environment, task, cmdopts, Bunch, path, call_task, might_call, consume_args
# These 2 packages do magic on import, even though they aren't used explicitly
import paver.virtual
import paver.setuputils
from paver.shell import sh
from paver.setuputils import setup, find_package_data, find_packages

sphinxcontrib = False
try:
    from sphinxcontrib import paverutils
    sphinxcontrib = True
except ImportError:
    pass

sys.path.insert(0, '')

options = environment.options

install_requires = [
    'FeedParser>=5.2.1',
    # There is a bug in sqlalchemy 0.9.0, see gh#127
    'SQLAlchemy >=0.7.5, !=0.9.0, <1.999',
    'PyYAML',
    # There is a bug in beautifulsoup 4.2.0 that breaks imdb parsing, see http://flexget.com/ticket/2091
    'beautifulsoup4>=4.1, !=4.2.0, <4.5',
    'html5lib>=0.11',
    'PyRSS2Gen',
    'pynzb',
    'progressbar',
    'rpyc',
    'jinja2',
    # There is a bug in requests 2.4.0 where it leaks urllib3 exceptions
    'requests>=1.0, !=2.4.0, <2.99',
    'python-dateutil!=2.0, !=2.2',
    'jsonschema>=2.0',
    'tmdb3',
    'path.py',
    'guessit>=2.0rc5',
    'apscheduler',
    'flask>=0.7',
    'flask-restful>=0.3.3',
    'ordereddict>=1.1',
    'flask-restplus==0.7.2',
    'cherrypy>=3.7.0',
    'flask-assets>=0.11',
    'cssmin>=0.2.0',
    'flask-compress>=1.2.1',
    'flask-login>=0.3.2',
    'pyparsing>=2.0.3',
    'pyScss>=1.3.4',
    'pytvmaze>=1.4.4'
]

if sys.version_info < (2, 7):
    # argparse is part of the standard library in python 2.7+
    install_requires.append('argparse')

entry_points = {'console_scripts': ['flexget = flexget:main']}

# Provide an alternate exe on windows which does not cause a pop-up when scheduled
if sys.platform.startswith('win'):
    entry_points.setdefault('gui_scripts', []).append('flexget-headless = flexget:main')

with open("README.rst") as readme:
    long_description = readme.read()

# Populates __version__ without importing the package
__version__ = None
execfile('flexget/_version.py')
if not __version__:
    print('Could not find __version__ from flexget/_version.py')
    sys.exit(1)

setup(
    name='FlexGet',
    version=__version__,  # release task may edit this
    description='FlexGet is a program aimed to automate downloading or processing content (torrents, podcasts, etc.) '
                'from different sources like RSS-feeds, html-pages, various sites and more.',
    long_description=long_description,
    author='Marko Koivusalo',
    author_email='marko.koivusalo@gmail.com',
    license='MIT',
    url='http://flexget.com',
    download_url='http://download.flexget.com',
    install_requires=install_requires,
    packages=find_packages(exclude=['tests']),
    package_data=find_package_data('flexget', package='flexget',
                                   exclude=['FlexGet.egg-info', '*.pyc'],
                                   exclude_directories=['node_modules', 'bower_components'],
                                   only_in_packages=False),  # NOTE: the exclude does not seem to work
    zip_safe=False,
    test_suite='nose.collector',
    extras_require={
        'memusage': ['guppy'],
        'NZB': ['pynzb'],
        'TaskTray': ['pywin32'],
    },
    entry_points=entry_points,
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
    ]

)

options(
    minilib=Bunch(
        # 'version' is included as workaround to https://github.com/paver/paver/issues/112, TODO: remove
        extra_files=['virtual', 'svn', 'version']
    ),
    virtualenv=Bunch(
        paver_command_line='develop'
    ),
    # sphinxcontrib.paverutils
    sphinx=Bunch(
        docroot='docs',
        builddir='build',
        builder='html',
        confdir='docs'
    ),
)

def set_init_version(ver):
    """Replaces the version with ``ver`` in _version.py"""
    import fileinput
    for line in fileinput.FileInput('flexget/_version.py', inplace=1):
        if line.startswith('__version__ = '):
            line = "__version__ = '%s'\n" % ver
        print(line, end='')

@task
def version():
    """Prints the version number of the source"""
    print(__version__)

@task
@cmdopts([('dev', None, 'Bumps to new development version instead of release version.')])
def increment_version(options):
    """Increments either release or dev version by 1"""
    print('current version: %s' % __version__)
    ver_split = __version__.split('.')
    dev = options.increment_version.get('dev')
    if 'dev' in ver_split[-1]:
        if dev:
            # If this is already a development version, increment the dev count by 1
            ver_split[-1] = 'dev%d' % (int(ver_split[-1].strip('dev') or 0) + 1)
        else:
            # Just strip off dev tag for next release version
            ver_split = ver_split[:-1]
    else:
        # Increment the revision number by one
        if len(ver_split) == 2:
            # We don't have a revision number, assume 0
            ver_split.append('1')
        else:
            ver_split[-1] = str(int(ver_split[-1]) + 1)
        if dev:
            ver_split.append('dev')
    new_version = '.'.join(ver_split)
    print('new version: %s' % new_version)
    set_init_version(new_version)

@task
@cmdopts([
    ('online', None, 'Run online tests')
])
def test(options):
    """Run FlexGet unit tests"""
    options.setdefault('test', Bunch())
    import nose
    from nose.plugins.manager import DefaultPluginManager

    cfg = nose.config.Config(plugins=DefaultPluginManager(), verbosity=2)

    args = []
    # Adding the -v flag makes the tests fail in python 2.7
    #args.append('-v')
    args.append('--processes=4')
    args.append('-x')
    if not options.test.get('online'):
        args.append('--attr=!online')
    args.append('--where=tests')

    # Store current path since --where changes it, restore when leaving
    cwd = os.getcwd()
    try:
        return nose.run(argv=args, config=cfg)
    finally:
        os.chdir(cwd)

@task
def clean():
    """Cleans up the virtualenv"""
    for p in ('bin', 'Scripts', 'build', 'dist', 'include', 'lib', 'man',
              'share', 'FlexGet.egg-info', 'paver-minilib.zip', 'setup.py'):
        pth = path(p)
        if pth.isdir():
            pth.rmtree()
        elif pth.isfile():
            pth.remove()

    for pkg in set(options.setup.packages) | set(('tests',)):
        for filename in glob.glob(pkg.replace('.', os.sep) + "/*.py[oc~]"):
            path(filename).remove()

@task
@cmdopts([
    ('dist-dir=', 'd', 'directory to put final built distributions in'),
    ('revision=', 'r', 'minor revision number of this build')
])
def sdist(options):
    """Build tar.gz distribution package"""
    print('sdist version: %s' % __version__)
    # clean previous build
    print('Cleaning build...')
    for p in ['build']:
        pth = path(p)
        if pth.isdir():
            pth.rmtree()
        elif pth.isfile():
            pth.remove()
        else:
            print('Unable to remove %s' % pth)

    # remove pre-compiled pycs from tests, I don't know why paver even tries to include them ...
    # seems to happen only with sdist though
    for pyc in path('tests/').files('*.pyc'):
        pyc.remove()

    for t in ['minilib', 'generate_setup', 'setuptools.command.sdist']:
        call_task(t)

@task
def coverage():
    """Make coverage.flexget.com"""
    # --with-coverage --cover-package=flexget --cover-html --cover-html-dir /var/www/flexget_coverage/
    import nose
    from nose.plugins.manager import DefaultPluginManager

    cfg = nose.config.Config(plugins=DefaultPluginManager(), verbosity=2)
    argv = ['bin/paver']
    argv.extend(['--attr=!online'])
    argv.append('--with-coverage')
    argv.append('--cover-html')
    argv.extend(['--cover-package', 'flexget'])
    argv.extend(['--cover-html-dir', '/var/www/flexget_coverage/'])
    nose.run(argv=argv, config=cfg)
    print('Coverage generated')

@task
@cmdopts([
    ('docs-dir=', 'd', 'directory to put the documetation in')
])
def docs():
    if not sphinxcontrib:
        print('ERROR: requires sphinxcontrib-paverutils')
        sys.exit(1)
    from paver import tasks
    if not os.path.exists('build'):
        os.mkdir('build')
    if not os.path.exists(os.path.join('build', 'sphinx')):
        os.mkdir(os.path.join('build', 'sphinx'))

    setup_section = tasks.environment.options.setdefault("sphinx", Bunch())
    setup_section.update(outdir=options.docs.get('docs_dir', 'build/sphinx'))
    call_task('sphinxcontrib.paverutils.html')

@task
@might_call('test', 'sdist')
@cmdopts([('no-tests', None, 'skips unit tests')])
def release(options):
    """Run tests then make an sdist if successful."""
    if not options.release.get('no_tests'):
        if not test():
            print('Unit tests did not pass')
            sys.exit(1)

    print('Making src release')
    sdist()

@task
def install_tools():
    """Install development / jenkins tools and dependencies"""

    try:
        import pip
    except ImportError:
        print('FATAL: Unable to import pip, please install it and run this again!')
        sys.exit(1)

    try:
        import sphinxcontrib
        print('sphinxcontrib INSTALLED')
    except ImportError:
        pip.main(['install', 'sphinxcontrib-paverutils'])

    pip.main(['install', '-r', 'jenkins-requirements.txt'])

@task
def clean_compiled():
    for root, dirs, files in os.walk('flexget'):
        for name in files:
            fqn = os.path.join(root, name)
            if fqn[-3:] == 'pyc' or fqn[-3:] == 'pyo' or fqn[-5:] == 'cover':
                print('Deleting %s' % fqn)
                os.remove(fqn)

@task
@consume_args
def pep8(args):
    try:
        import pep8
    except:
        print('Run bin/paver install_tools')
        sys.exit(1)

    # Ignoring certain errors
    ignore = [
        'E711', 'E712',  # These are comparisons to singletons i.e. == False, and == None. We need these for sqlalchemy.
        'W291', 'W293', 'E261',
        'E128'  # E128 continuation line under-indented for visual indent
    ]
    styleguide = pep8.StyleGuide(show_source=True, ignore=ignore, repeat=1, max_line_length=120,
                                 parse_argv=args)
    styleguide.input_dir('flexget')

@task
@cmdopts([
    ('file=', 'f', 'name of the requirements file to create')
])
def requirements(options):
    filename = options.requirements.get('file', 'requirements.txt')
    with open(filename, mode='w') as req_file:
        req_file.write('\n'.join(options.install_requires))

@task
def build_webui():

    cwd = os.path.join('flexget', 'ui')

    # Cleanup previous builds
    for folder in ['bower_components' 'node_modules']:
        folder = os.path.join(cwd, folder)
        if os.path.exists(folder):
            shutil.rmtree(folder)

    # Install npm packages
    sh(['npm', 'install'], cwd=cwd)

    # Build the ui
    sh(['bower', 'install'], cwd=cwd)

    # Build the ui
    sh('gulp', cwd=cwd)
<commit_msg>Upgrade to flask-restplus 0.8.6<commit_after>"""
FlexGet build and development utilities - unfortunately this file is somewhat messy
"""
from __future__ import print_function
import glob
import os
import shutil
import sys

from paver.easy import environment, task, cmdopts, Bunch, path, call_task, might_call, consume_args
# These 2 packages do magic on import, even though they aren't used explicitly
import paver.virtual
import paver.setuputils
from paver.shell import sh
from paver.setuputils import setup, find_package_data, find_packages

sphinxcontrib = False
try:
    from sphinxcontrib import paverutils
    sphinxcontrib = True
except ImportError:
    pass

sys.path.insert(0, '')

options = environment.options

install_requires = [
    'FeedParser>=5.2.1',
    # There is a bug in sqlalchemy 0.9.0, see gh#127
    'SQLAlchemy >=0.7.5, !=0.9.0, <1.999',
    'PyYAML',
    # There is a bug in beautifulsoup 4.2.0 that breaks imdb parsing, see http://flexget.com/ticket/2091
    'beautifulsoup4>=4.1, !=4.2.0, <4.5',
    'html5lib>=0.11',
    'PyRSS2Gen',
    'pynzb',
    'progressbar',
    'rpyc',
    'jinja2',
    # There is a bug in requests 2.4.0 where it leaks urllib3 exceptions
    'requests>=1.0, !=2.4.0, <2.99',
    'python-dateutil!=2.0, !=2.2',
    'jsonschema>=2.0',
    'tmdb3',
    'path.py',
    'guessit>=2.0rc5',
    'apscheduler',
    'flask>=0.7',
    'flask-restful>=0.3.3',
    'ordereddict>=1.1',
    'flask-restplus==0.8.6',
    'cherrypy>=3.7.0',
    'flask-assets>=0.11',
    'cssmin>=0.2.0',
    'flask-compress>=1.2.1',
    'flask-login>=0.3.2',
    'pyparsing>=2.0.3',
    'pyScss>=1.3.4',
    'pytvmaze>=1.4.4'
]

if sys.version_info < (2, 7):
    # argparse is part of the standard library in python 2.7+
    install_requires.append('argparse')

entry_points = {'console_scripts': ['flexget = flexget:main']}

# Provide an alternate exe on windows which does not cause a pop-up when scheduled
if sys.platform.startswith('win'):
    entry_points.setdefault('gui_scripts', []).append('flexget-headless = flexget:main')

with open("README.rst") as readme:
    long_description = readme.read()

# Populates __version__ without importing the package
__version__ = None
execfile('flexget/_version.py')
if not __version__:
    print('Could not find __version__ from flexget/_version.py')
    sys.exit(1)

setup(
    name='FlexGet',
    version=__version__,  # release task may edit this
    description='FlexGet is a program aimed to automate downloading or processing content (torrents, podcasts, etc.) '
                'from different sources like RSS-feeds, html-pages, various sites and more.',
    long_description=long_description,
    author='Marko Koivusalo',
    author_email='marko.koivusalo@gmail.com',
    license='MIT',
    url='http://flexget.com',
    download_url='http://download.flexget.com',
    install_requires=install_requires,
    packages=find_packages(exclude=['tests']),
    package_data=find_package_data('flexget', package='flexget',
                                   exclude=['FlexGet.egg-info', '*.pyc'],
                                   exclude_directories=['node_modules', 'bower_components'],
                                   only_in_packages=False),  # NOTE: the exclude does not seem to work
    zip_safe=False,
    test_suite='nose.collector',
    extras_require={
        'memusage': ['guppy'],
        'NZB': ['pynzb'],
        'TaskTray': ['pywin32'],
    },
    entry_points=entry_points,
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
    ]

)

options(
    minilib=Bunch(
        # 'version' is included as workaround to https://github.com/paver/paver/issues/112, TODO: remove
        extra_files=['virtual', 'svn', 'version']
    ),
    virtualenv=Bunch(
        paver_command_line='develop'
    ),
    # sphinxcontrib.paverutils
    sphinx=Bunch(
        docroot='docs',
        builddir='build',
        builder='html',
        confdir='docs'
    ),
)

def set_init_version(ver):
    """Replaces the version with ``ver`` in _version.py"""
    import fileinput
    for line in fileinput.FileInput('flexget/_version.py', inplace=1):
        if line.startswith('__version__ = '):
            line = "__version__ = '%s'\n" % ver
        print(line, end='')

@task
def version():
    """Prints the version number of the source"""
    print(__version__)

@task
@cmdopts([('dev', None, 'Bumps to new development version instead of release version.')])
def increment_version(options):
    """Increments either release or dev version by 1"""
    print('current version: %s' % __version__)
    ver_split = __version__.split('.')
    dev = options.increment_version.get('dev')
    if 'dev' in ver_split[-1]:
        if dev:
            # If this is already a development version, increment the dev count by 1
            ver_split[-1] = 'dev%d' % (int(ver_split[-1].strip('dev') or 0) + 1)
        else:
            # Just strip off dev tag for next release version
            ver_split = ver_split[:-1]
    else:
        # Increment the revision number by one
        if len(ver_split) == 2:
            # We don't have a revision number, assume 0
            ver_split.append('1')
        else:
            ver_split[-1] = str(int(ver_split[-1]) + 1)
        if dev:
            ver_split.append('dev')
    new_version = '.'.join(ver_split)
    print('new version: %s' % new_version)
    set_init_version(new_version)

@task
@cmdopts([
    ('online', None, 'Run online tests')
])
def test(options):
    """Run FlexGet unit tests"""
    options.setdefault('test', Bunch())
    import nose
    from nose.plugins.manager import DefaultPluginManager

    cfg = nose.config.Config(plugins=DefaultPluginManager(), verbosity=2)

    args = []
    # Adding the -v flag makes the tests fail in python 2.7
    #args.append('-v')
    args.append('--processes=4')
    args.append('-x')
    if not options.test.get('online'):
        args.append('--attr=!online')
    args.append('--where=tests')

    # Store current path since --where changes it, restore when leaving
    cwd = os.getcwd()
    try:
        return nose.run(argv=args, config=cfg)
    finally:
        os.chdir(cwd)

@task
def clean():
    """Cleans up the virtualenv"""
    for p in ('bin', 'Scripts', 'build', 'dist', 'include', 'lib', 'man',
              'share', 'FlexGet.egg-info', 'paver-minilib.zip', 'setup.py'):
        pth = path(p)
        if pth.isdir():
            pth.rmtree()
        elif pth.isfile():
            pth.remove()

    for pkg in set(options.setup.packages) | set(('tests',)):
        for filename in glob.glob(pkg.replace('.', os.sep) + "/*.py[oc~]"):
            path(filename).remove()

@task
@cmdopts([
    ('dist-dir=', 'd', 'directory to put final built distributions in'),
    ('revision=', 'r', 'minor revision number of this build')
])
def sdist(options):
    """Build tar.gz distribution package"""
    print('sdist version: %s' % __version__)
    # clean previous build
    print('Cleaning build...')
    for p in ['build']:
        pth = path(p)
        if pth.isdir():
            pth.rmtree()
        elif pth.isfile():
            pth.remove()
        else:
            print('Unable to remove %s' % pth)

    # remove pre-compiled pycs from tests, I don't know why paver even tries to include them ...
    # seems to happen only with sdist though
    for pyc in path('tests/').files('*.pyc'):
        pyc.remove()

    for t in ['minilib', 'generate_setup', 'setuptools.command.sdist']:
        call_task(t)

@task
def coverage():
    """Make coverage.flexget.com"""
    # --with-coverage --cover-package=flexget --cover-html --cover-html-dir /var/www/flexget_coverage/
    import nose
    from nose.plugins.manager import DefaultPluginManager

    cfg = nose.config.Config(plugins=DefaultPluginManager(), verbosity=2)
    argv = ['bin/paver']
    argv.extend(['--attr=!online'])
    argv.append('--with-coverage')
    argv.append('--cover-html')
    argv.extend(['--cover-package', 'flexget'])
    argv.extend(['--cover-html-dir', '/var/www/flexget_coverage/'])
    nose.run(argv=argv, config=cfg)
    print('Coverage generated')

@task
@cmdopts([
    ('docs-dir=', 'd', 'directory to put the documetation in')
])
def docs():
    if not sphinxcontrib:
        print('ERROR: requires sphinxcontrib-paverutils')
        sys.exit(1)
    from paver import tasks
    if not os.path.exists('build'):
        os.mkdir('build')
    if not os.path.exists(os.path.join('build', 'sphinx')):
        os.mkdir(os.path.join('build', 'sphinx'))

    setup_section = tasks.environment.options.setdefault("sphinx", Bunch())
    setup_section.update(outdir=options.docs.get('docs_dir', 'build/sphinx'))
    call_task('sphinxcontrib.paverutils.html')

@task
@might_call('test', 'sdist')
@cmdopts([('no-tests', None, 'skips unit tests')])
def release(options):
    """Run tests then make an sdist if successful."""
    if not options.release.get('no_tests'):
        if not test():
            print('Unit tests did not pass')
            sys.exit(1)

    print('Making src release')
    sdist()

@task
def install_tools():
    """Install development / jenkins tools and dependencies"""

    try:
        import pip
    except ImportError:
        print('FATAL: Unable to import pip, please install it and run this again!')
        sys.exit(1)

    try:
        import sphinxcontrib
        print('sphinxcontrib INSTALLED')
    except ImportError:
        pip.main(['install', 'sphinxcontrib-paverutils'])

    pip.main(['install', '-r', 'jenkins-requirements.txt'])

@task
def clean_compiled():
    for root, dirs, files in os.walk('flexget'):
        for name in files:
            fqn = os.path.join(root, name)
            if fqn[-3:] == 'pyc' or fqn[-3:] == 'pyo' or fqn[-5:] == 'cover':
                print('Deleting %s' % fqn)
                os.remove(fqn)

@task
@consume_args
def pep8(args):
    try:
        import pep8
    except:
        print('Run bin/paver install_tools')
        sys.exit(1)

    # Ignoring certain errors
    ignore = [
        'E711', 'E712',  # These are comparisons to singletons i.e. == False, and == None. We need these for sqlalchemy.
        'W291', 'W293', 'E261',
        'E128'  # E128 continuation line under-indented for visual indent
    ]
    styleguide = pep8.StyleGuide(show_source=True, ignore=ignore, repeat=1, max_line_length=120,
                                 parse_argv=args)
    styleguide.input_dir('flexget')

@task
@cmdopts([
    ('file=', 'f', 'name of the requirements file to create')
])
def requirements(options):
    filename = options.requirements.get('file', 'requirements.txt')
    with open(filename, mode='w') as req_file:
        req_file.write('\n'.join(options.install_requires))

@task
def build_webui():

    cwd = os.path.join('flexget', 'ui')

    # Cleanup previous builds
    for folder in ['bower_components' 'node_modules']:
        folder = os.path.join(cwd, folder)
        if os.path.exists(folder):
            shutil.rmtree(folder)

    # Install npm packages
    sh(['npm', 'install'], cwd=cwd)

    # Build the ui
    sh(['bower', 'install'], cwd=cwd)

    # Build the ui
    sh('gulp', cwd=cwd)
<|endoftext|>


<commit_before>#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import paver.doctools

from paver.easy import *
from paver.setuputils import setup, find_packages

def requirements():
    with open('requirements.txt') as handle:
        return handle.read().splitlines()

setup(
    name='CLIapp',
    version='1.0',
    packages=find_packages(exclude=['tests']),
    entry_points={'console_scripts': ['cliapp=cli_app.cli:main'], },
    package_data={
        '': [
            'pavement.py',
            'setup.py',
            'README.rst',
            'requirements.txt',
        ],
    },
    install_requires=requirements(),
    zip_safe=True,

    # Metadata for PyPI upload
    description='CLI example application',
    author='Your Name',
    author_email='you@example.com',
    url='https://github.com/xamurej/py3-cli-skel',
    # The complete list of classifiers can be checked at
    # <https://pypi.python.org/pypi?%3Aaction=list_classifiers>
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: Console',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python',
        'Topic :: Software Development :: Documentation',
        'Topic :: Software Development :: Testing',
        'Topic :: Software Development',
        'Topic :: Utilities',
    ], )
<commit_msg>fixed inclusion of requirements.txt<commit_after>#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from paver.setuputils import setup, find_packages

def requirements():
    with open('requirements.txt') as handle:
        return handle.read().splitlines()

setup(
    name='CLIapp',
    version='1.0',
    packages=find_packages(exclude=['tests']),
    entry_points={'console_scripts': ['cliapp=cli_app.cli:main'], },
    package_data={
        '': [
            'pavement.py',
            'setup.py',

        ],
    },
    data_files=[('', ['README.rst', 'requirements.txt'])],
    install_requires=requirements(),
    zip_safe=True,

    # Metadata for PyPI upload
    description='CLI example application',
    author='Your Name',
    author_email='you@example.com',
    url='https://github.com/xamurej/py3-cli-skel',
    # The complete list of classifiers can be checked at
    # <https://pypi.python.org/pypi?%3Aaction=list_classifiers>
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: Console',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python',
        'Topic :: Software Development :: Documentation',
        'Topic :: Software Development :: Testing',
        'Topic :: Software Development',
        'Topic :: Utilities',
    ], )
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Convenience functions for in memory deduplication
"""

import collections
import dedupe.core

def dataSample(data, sample_size, constrained_matching=False):
    '''Randomly sample pairs of records from a data dictionary'''

    data_list = data.values()

    if constrained_matching:
        data_list_A = []
        data_list_B = []

        for record in data_list:
            if record['dataset'] == 0:
                data_list_A.append(record)
            else:
                data_list_B.append(record)

        n_records = len(data_list_A) if len(data_list_A) < len(data_list_B) else len(data_list_B)

        random_pairs = dedupe.core.randomPairs(n_records, sample_size)

        return tuple((data_list_A[int(k1)], data_list_B[int(k2)]) for k1, k2 in random_pairs)
    else:
        random_pairs = dedupe.core.randomPairs(len(data_list), sample_size)

        return tuple((data_list[int(k1)], data_list[int(k2)]) for k1, k2 in random_pairs)

def blockData(data_d, blocker, constrained_matching=False):

    blocks = dedupe.core.OrderedDict({})
    record_blocks = dedupe.core.OrderedDict({})
    key_blocks = dedupe.core.OrderedDict({})

    blocker.tfIdfBlocks(data_d.iteritems(), constrained_matching)

    for (record_id, record) in data_d.iteritems():
        for key in blocker((record_id, record)):
            blocks.setdefault(key, {}).update({record_id : record})

    blocked_records = tuple(block for block in blocks.values())

    return blocked_records

<commit_msg>Use min() instead of if and else comparison<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Convenience functions for in memory deduplication
"""

import collections
import dedupe.core

def dataSample(data, sample_size, constrained_matching=False):
    '''Randomly sample pairs of records from a data dictionary'''

    data_list = data.values()

    if constrained_matching:
        data_list_A = []
        data_list_B = []

        for record in data_list:
            if record['dataset'] == 0:
                data_list_A.append(record)
            else:
                data_list_B.append(record)

        n_records = min(len(data_list_A), len(data_list_B))

        random_pairs = dedupe.core.randomPairs(n_records, sample_size)

        return tuple((data_list_A[int(k1)], data_list_B[int(k2)]) for k1, k2 in random_pairs)
    else:
        random_pairs = dedupe.core.randomPairs(len(data_list), sample_size)

        return tuple((data_list[int(k1)], data_list[int(k2)]) for k1, k2 in random_pairs)

def blockData(data_d, blocker, constrained_matching=False):

    blocks = dedupe.core.OrderedDict({})
    record_blocks = dedupe.core.OrderedDict({})
    key_blocks = dedupe.core.OrderedDict({})

    blocker.tfIdfBlocks(data_d.iteritems(), constrained_matching)

    for (record_id, record) in data_d.iteritems():
        for key in blocker((record_id, record)):
            blocks.setdefault(key, {}).update({record_id : record})

    blocked_records = tuple(block for block in blocks.values())

    return blocked_records

<|endoftext|>


<commit_before>import os
#import logging
from datetime import datetime, timedelta
from threading import Lock
import re
import time
from flask import Flask, jsonify, request, make_response, Response, json, url_for

# Create Flask application
app = Flask(__name__)
#app.config['LOGGING_LEVEL'] = logging.INFO

# Lock for thread-safe counter increment
lock = Lock()

# Status Codes
# will be replaced eventually
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_204_NO_CONTENT = 204
HTTP_400_BAD_REQUEST = 400
HTTP_404_NOT_FOUND = 404
HTTP_409_CONFLICT = 409

# Error Messages
CONTENT_ERR_MSG = "Content type of the request is not json. Doesn't support other formats now."

#starter payment models for mvp
#dummy data
current_payment_id = 3;
credit = {'name' : 'John Johnson',
		  'number' : '1234567898765432',
		  'expires' : '01/2020',
		  'type' : 'American Express'}

debit = {'name' : 'Jane Jenkins',
		 'number' : '9876543212345678',
		 'expires' : '08/2018',
		 'type' : "Visa"}

paypal = {'name' : 'Joe Jetson',
		  'e-mail' : 'joe@aol.com',
		  'linked' : True}

payments = [{'id' : 1, 'default' : True, 'nickname' : 'my-credit',
			 'type' : 'credit', 'charge-history': 0.00, 'detail' : credit},
			{'id' : 2, 'default' : False, 'nickname' : 'my-debit',
			 'type' : 'debit', 'charge-history': 0.00,'detail' : debit},
			{'id' : 3, 'default' : False, 'nickname' : 'my-paypal',
			 'type' : 'paypal', 'charge-history': 0.00,'detail' : paypal}]

######################################################################
# GET INDEX
######################################################################
@app.route('/')
def index():
	payments_url = request.base_url + "payments"
	#to do: change this to work with remplates
	#need to reorganize directory
	return app.send_static_file('index.html')

######################################################################
# LIST ALL PAYMENTS
######################################################################
@app.route('/payments', methods=['GET'])
def list_payments():
	if request.query_string != "":
		return query_payments()
	results = []
	type = request.args.get('type')
	if type:
		results = [payment for payment in payments if payment['type'] == type]
	else:
		results = payments

	return make_response(jsonify(results), HTTP_200_OK)

######################################################################
# ADD A NEW PAYMENT
######################################################################
@app.route('/payments', methods=['POST'])
def add_payment():
	data = request.get_json(silent=True)
	if data is None:
		return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)

	if is_valid(data):
		id = index_inc()

		newData = {'id' : id, 'default' : False, 'charge-history' : 0.0,
               'nickname' : data['nickname'], 'type' : data['type'], 'detail' : data['detail']}

		payments.append(newData)
		message = {'successfully created' : payments[len(payments)-1]}
		rc = HTTP_201_CREATED
	else:
		message = {'error' : 'Data is not valid.' }
		rc = HTTP_400_BAD_REQUEST

	response = make_response(jsonify(message), rc)
	if rc == HTTP_201_CREATED:
		response.headers['Location'] = url_for('get_payments', id = id)
	return response

######################################################################
# SET DEFAULT PAYMENT (ACTION)
######################################################################
@app.route('/payments/<int:id>/set-default', methods=['PUT'])
def set_default(id):
	if id > current_payment_id or id < 1:
		message = { 'error' : 'Payment with id: %s was not found' % str(id) }
		rc = HTTP_404_NOT_FOUND
	else:
		index = [i for i, payment in enumerate(payments) if payment['id'] == id]
		if len(index) <= 0:
			message = { 'error' : 'Payment with id: %s was not found' % str(id) }
			rc = HTTP_404_NOT_FOUND
		else:
			for payment in payments:
				payment['default'] = False
			payments[index[0]]['default'] = True
			message = { 'success' : 'Payment with id: %s set as default.' % str(id) }
			rc = HTTP_200_OK
	return make_response(jsonify(message), rc)

######################################################################
# RETRIEVE A PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['GET'])
def get_payments(id):
	index = [i for i, payment in enumerate(payments) if payment['id'] == id]
	if len(index) > 0:
		message = payments[index[0]]
		rc = HTTP_200_OK
	else:
		message = { 'error' : 'Payment with id: %s was not found' % str(id) }
		rc = HTTP_404_NOT_FOUND

	return make_response(jsonify(message), rc)

######################################################################
# RETRIEVE A PAYMENT ON QUERY
######################################################################
def query_payments():

	q = request.query_string
	key = re.search('\w*', q)
	key = key.group(0)
	value = re.search('=\w*', q)
	value = value.group(0)[1::]

	list=[]
	for p in payments:
		if p.has_key(key):
			if p[key] == value:
				list.append(p)
		else:
			message = { 'error' : '%s is not a valid key' % key }
			rc = HTTP_404_NOT_FOUND
			return make_response(jsonify(message), rc)

	if len(list) > 0:
   		message = list
   		rc = HTTP_200_OK
	else:
   		message = { 'error' : 'Payment with %s: %s was not found' % (key,value) }
   		rc = HTTP_404_NOT_FOUND
   	return make_response(jsonify(message), rc)

######################################################################
# UPDATE AN EXISTING PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['PUT'])
def update_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        if not request.is_json:
    		return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)
        payload = request.get_json()
        if is_valid(payload):
            payments[index[0]] = {'id' : id, 'nickname' : payload['nickname'], 'type' : payload['type'],
            					  'default' : payments[index[0]]['default'],
            					  'charge-history' : payments[index[0]]['charge-history'],
            					  'detail' : payload['detail']}
            message = payments[index[0]]
            rc = HTTP_200_OK
        else:
            message = { 'error' : 'Payments data was not valid' }
            rc = HTTP_400_BAD_REQUEST
    else:
        message = { 'error' : 'Payments %s was not found' % id }
        rc = HTTP_404_NOT_FOUND

    return make_response(jsonify(message), rc)

######################################################################
# UPDATE AN EXISTING PAYMENT PARTIALLY
######################################################################
@app.route('/payments/<int:id>', methods=['PATCH'])
def update_partial_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        if not request.is_json:
    		    return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)
        payload = request.get_json()
        if is_valid_patch(payload):
            target_payment = payments[index[0]]
            # for now, can only update partially with nickname, type and detail
            payload_nickname = target_payment['nickname'] if 'nickname' not in payload else payload['nickname']
            payload_type = target_payment['type'] if 'type' not in payload else payload['type']
            payload_detail = target_payment['detail'] if 'detail' not in payload else payload['detail']
            payments[index[0]] = {'id' : id, 'nickname' : payload_nickname, 'default' : target_payment['default'],
                'charge-history' : target_payment['charge-history'], 'type' : payload_type, 'detail' : payload_detail}
            message = payments[index[0]]
            rc = HTTP_200_OK
        else:
            message = { 'error' : 'Payments data was not valid' }
            rc = HTTP_400_BAD_REQUEST
    else:
        message = { 'error' : 'Payments %s was not found' % id }
        rc = HTTP_404_NOT_FOUND

    return make_response(jsonify(message), rc)

######################################################################
# DELETE A PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['DELETE'])
def delete_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        del payments[index[0]]
    return '', HTTP_204_NO_CONTENT

######################################################################
# CHARGE PAYMENT (ACTION)
######################################################################

@app.route('/payments/charge', methods=['PUT'])
def charge_payment():
	rc = HTTP_400_BAD_REQUEST
	charge = request.get_json(silent=True)
	if charge is None:
		return make_response(CONTENT_ERR_MSG, rc)
	if not is_positive(charge['amount']):
		message = {'error' : ('Invalid order amount. Transaction cancelled. ',
							  'Please check your order and try again.')}
	else:
		index = [i for i, payment in enumerate(payments) if payment['default']]
		if len(index) < 1:
			message = {'error' : 'No default payment method selected. Transaction cancelled'}
			return make_response(jsonify(message), rc)
		p = payments[index[0]]

		if p['type'] == 'paypal' and not p['detail']['linked']:
			message = {'error' : ('Your paypal account has not been linked. Transaction cancelled. ',
								  'Please update your account and try your order again.')}
		elif p['type'] != 'paypal' and is_expired(p):
			message = {'error' : ('Your credit/debit card has expired. Transaction cancelled. ',
								  'Please update your account and try your order again.')}
		else:
			p['charge-history'] = p['charge-history'] + charge['amount']
			message = {'success' : 'Your payment method %s has been charged $%.2f' % (p['nickname'], charge['amount'])}
			rc = HTTP_200_OK

	return make_response(jsonify(message), rc)

######################################################################
#   U T I L I T I E S
######################################################################
def index_inc():
	global current_payment_id
	with lock:
		current_payment_id += 1
	return current_payment_id

def is_valid(data):
	valid = False
	valid_detail = False
	try:
		nickname = data['nickname']
		type = data['type']
		detail = data['detail']

		if bool(re.search(r'\d', detail['name'])) == False:
			valid = True

		if type == 'credit' or type == 'debit':
			name = detail['name']
			card_number = detail['number']
			expires_date = detail['expires']
			subtype = detail['type']

		if bool(re.match('^[0-9]+$', card_number)) and (len(card_number) == 16):
			datetime.strptime(expires_date, '%m/%Y')
			valid_detail = True
    #except KeyError as err:
    #app.logger.warn('Missing parameter error: %s', err)
    #    pass
    #except TypeError:
    #app.logger.warn('Invalid Content Type error')
    #    pass
    #except ValueError:
    #app.logger.warn('Invalid Content Type error')
    #   pass
	except:
		pass
	return valid & valid_detail

def is_expired(payment):
	#get datetime object for last day of expiring month
	exp_date = payment['detail']['expires']
	month = int(exp_date[:2]) + 1
	exp_date = '%s%s' % (month, exp_date[2:])
	exp_date = datetime.strptime(exp_date, '%m/%Y')
	exp_date = exp_date - timedelta(1)
	exp_date = datetime.date(exp_date)

	now = datetime.now()
	now = datetime.date(now)

	if(now < exp_date):
		return False
	else:
		return True

def is_positive(amount):
	if(amount > 0):
		return True
	else:
		return False

def is_valid_patch(data):
	#update later for validating data for PATCH method
	return True

######################################################################
#   M A I N
######################################################################
if __name__ == '__main__':
	debug = (os.getenv('DEBUG', 'False') == 'True')
	port = os.getenv('PORT', '5000')
	app.run(host='0.0.0.0', port=int(port), debug=debug)
<commit_msg>fix the bug: cannot add a paypal payment<commit_after>import os
#import logging
from datetime import datetime, timedelta
from threading import Lock
import re
import time
from flask import Flask, jsonify, request, make_response, Response, json, url_for

# Create Flask application
app = Flask(__name__)
#app.config['LOGGING_LEVEL'] = logging.INFO

# Lock for thread-safe counter increment
lock = Lock()

# Status Codes
# will be replaced eventually
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_204_NO_CONTENT = 204
HTTP_400_BAD_REQUEST = 400
HTTP_404_NOT_FOUND = 404
HTTP_409_CONFLICT = 409

# Error Messages
CONTENT_ERR_MSG = "Content type of the request is not json. Doesn't support other formats now."

#starter payment models for mvp
#dummy data
current_payment_id = 3;
credit = {'name' : 'John Johnson',
		  'number' : '1234567898765432',
		  'expires' : '01/2020',
		  'type' : 'American Express'}

debit = {'name' : 'Jane Jenkins',
		 'number' : '9876543212345678',
		 'expires' : '08/2018',
		 'type' : "Visa"}

paypal = {'name' : 'Joe Jetson',
		  'e-mail' : 'joe@aol.com',
		  'linked' : True}

payments = [{'id' : 1, 'default' : True, 'nickname' : 'my-credit',
			 'type' : 'credit', 'charge-history': 0.00, 'detail' : credit},
			{'id' : 2, 'default' : False, 'nickname' : 'my-debit',
			 'type' : 'debit', 'charge-history': 0.00,'detail' : debit},
			{'id' : 3, 'default' : False, 'nickname' : 'my-paypal',
			 'type' : 'paypal', 'charge-history': 0.00,'detail' : paypal}]

######################################################################
# GET INDEX
######################################################################
@app.route('/')
def index():
	payments_url = request.base_url + "payments"
	#to do: change this to work with remplates
	#need to reorganize directory
	return app.send_static_file('index.html')

######################################################################
# LIST ALL PAYMENTS
######################################################################
@app.route('/payments', methods=['GET'])
def list_payments():
	if request.query_string != "":
		return query_payments()
	results = []
	type = request.args.get('type')
	if type:
		results = [payment for payment in payments if payment['type'] == type]
	else:
		results = payments

	return make_response(jsonify(results), HTTP_200_OK)

######################################################################
# ADD A NEW PAYMENT
######################################################################
@app.route('/payments', methods=['POST'])
def add_payment():
	data = request.get_json(silent=True)
	if data is None:
		return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)

	if is_valid(data):
		id = index_inc()

		newData = {'id' : id, 'default' : False, 'charge-history' : 0.0,
               'nickname' : data['nickname'], 'type' : data['type'], 'detail' : data['detail']}

		payments.append(newData)
		message = {'successfully created' : payments[len(payments)-1]}
		rc = HTTP_201_CREATED
	else:
		message = {'error' : 'Data is not valid.' }
		rc = HTTP_400_BAD_REQUEST

	response = make_response(jsonify(message), rc)
	if rc == HTTP_201_CREATED:
		response.headers['Location'] = url_for('get_payments', id = id)
	return response

######################################################################
# SET DEFAULT PAYMENT (ACTION)
######################################################################
@app.route('/payments/<int:id>/set-default', methods=['PUT'])
def set_default(id):
	if id > current_payment_id or id < 1:
		message = { 'error' : 'Payment with id: %s was not found' % str(id) }
		rc = HTTP_404_NOT_FOUND
	else:
		index = [i for i, payment in enumerate(payments) if payment['id'] == id]
		if len(index) <= 0:
			message = { 'error' : 'Payment with id: %s was not found' % str(id) }
			rc = HTTP_404_NOT_FOUND
		else:
			for payment in payments:
				payment['default'] = False
			payments[index[0]]['default'] = True
			message = { 'success' : 'Payment with id: %s set as default.' % str(id) }
			rc = HTTP_200_OK
	return make_response(jsonify(message), rc)

######################################################################
# RETRIEVE A PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['GET'])
def get_payments(id):
	index = [i for i, payment in enumerate(payments) if payment['id'] == id]
	if len(index) > 0:
		message = payments[index[0]]
		rc = HTTP_200_OK
	else:
		message = { 'error' : 'Payment with id: %s was not found' % str(id) }
		rc = HTTP_404_NOT_FOUND

	return make_response(jsonify(message), rc)

######################################################################
# RETRIEVE A PAYMENT ON QUERY
######################################################################
def query_payments():

	q = request.query_string
	key = re.search('\w*', q)
	key = key.group(0)
	value = re.search('=\w*', q)
	value = value.group(0)[1::]

	list=[]
	for p in payments:
		if p.has_key(key):
			if p[key] == value:
				list.append(p)
		else:
			message = { 'error' : '%s is not a valid key' % key }
			rc = HTTP_404_NOT_FOUND
			return make_response(jsonify(message), rc)

	if len(list) > 0:
   		message = list
   		rc = HTTP_200_OK
	else:
   		message = { 'error' : 'Payment with %s: %s was not found' % (key,value) }
   		rc = HTTP_404_NOT_FOUND
   	return make_response(jsonify(message), rc)

######################################################################
# UPDATE AN EXISTING PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['PUT'])
def update_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        if not request.is_json:
    		return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)
        payload = request.get_json()
        if is_valid(payload):
            payments[index[0]] = {'id' : id, 'nickname' : payload['nickname'], 'type' : payload['type'],
            					  'default' : payments[index[0]]['default'],
            					  'charge-history' : payments[index[0]]['charge-history'],
            					  'detail' : payload['detail']}
            message = payments[index[0]]
            rc = HTTP_200_OK
        else:
            message = { 'error' : 'Payments data was not valid' }
            rc = HTTP_400_BAD_REQUEST
    else:
        message = { 'error' : 'Payments %s was not found' % id }
        rc = HTTP_404_NOT_FOUND

    return make_response(jsonify(message), rc)

######################################################################
# UPDATE AN EXISTING PAYMENT PARTIALLY
######################################################################
@app.route('/payments/<int:id>', methods=['PATCH'])
def update_partial_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        if not request.is_json:
    		    return make_response(CONTENT_ERR_MSG, HTTP_400_BAD_REQUEST)
        payload = request.get_json()
        if is_valid_patch(payload):
            target_payment = payments[index[0]]
            # for now, can only update partially with nickname, type and detail
            payload_nickname = target_payment['nickname'] if 'nickname' not in payload else payload['nickname']
            payload_type = target_payment['type'] if 'type' not in payload else payload['type']
            payload_detail = target_payment['detail'] if 'detail' not in payload else payload['detail']
            payments[index[0]] = {'id' : id, 'nickname' : payload_nickname, 'default' : target_payment['default'],
                'charge-history' : target_payment['charge-history'], 'type' : payload_type, 'detail' : payload_detail}
            message = payments[index[0]]
            rc = HTTP_200_OK
        else:
            message = { 'error' : 'Payments data was not valid' }
            rc = HTTP_400_BAD_REQUEST
    else:
        message = { 'error' : 'Payments %s was not found' % id }
        rc = HTTP_404_NOT_FOUND

    return make_response(jsonify(message), rc)

######################################################################
# DELETE A PAYMENT
######################################################################
@app.route('/payments/<int:id>', methods=['DELETE'])
def delete_payments(id):
    index = [i for i, payment in enumerate(payments) if payment['id'] == id]
    if len(index) > 0:
        del payments[index[0]]
    return '', HTTP_204_NO_CONTENT

######################################################################
# CHARGE PAYMENT (ACTION)
######################################################################

@app.route('/payments/charge', methods=['PUT'])
def charge_payment():
	rc = HTTP_400_BAD_REQUEST
	charge = request.get_json(silent=True)
	if charge is None:
		return make_response(CONTENT_ERR_MSG, rc)
	if not is_positive(charge['amount']):
		message = {'error' : ('Invalid order amount. Transaction cancelled. ',
							  'Please check your order and try again.')}
	else:
		index = [i for i, payment in enumerate(payments) if payment['default']]
		if len(index) < 1:
			message = {'error' : 'No default payment method selected. Transaction cancelled'}
			return make_response(jsonify(message), rc)
		p = payments[index[0]]

		if p['type'] == 'paypal' and not p['detail']['linked']:
			message = {'error' : ('Your paypal account has not been linked. Transaction cancelled. ',
								  'Please update your account and try your order again.')}
		elif p['type'] != 'paypal' and is_expired(p):
			message = {'error' : ('Your credit/debit card has expired. Transaction cancelled. ',
								  'Please update your account and try your order again.')}
		else:
			p['charge-history'] = p['charge-history'] + charge['amount']
			message = {'success' : 'Your payment method %s has been charged $%.2f' % (p['nickname'], charge['amount'])}
			rc = HTTP_200_OK

	return make_response(jsonify(message), rc)

######################################################################
#   U T I L I T I E S
######################################################################
def index_inc():
	global current_payment_id
	with lock:
		current_payment_id += 1
	return current_payment_id

def is_valid(data):
	valid = False
	valid_detail = False
	try:
		nickname = data['nickname']
		type = data['type']
		detail = data['detail']

		if bool(re.search(r'\d', detail['name'])) == False:
			valid = True

		if type == 'credit' or type == 'debit':
			name = detail['name']
			card_number = detail['number']
			expires_date = detail['expires']
			subtype = detail['type']
			if bool(re.match('^[0-9]+$', card_number)) and (len(card_number) == 16):
				datetime.strptime(expires_date, '%m/%Y')
				valid_detail = True
		else:
			name = detail['name']
			email = detail['e-mail']
			linked = detail['linked']
			valid_detail = True;
    #except KeyError as err:
    #app.logger.warn('Missing parameter error: %s', err)
    #    pass
    #except TypeError:
    #app.logger.warn('Invalid Content Type error')
    #    pass
    #except ValueError:
    #app.logger.warn('Invalid Content Type error')
    #   pass
	except:
		pass
	return valid & valid_detail

def is_expired(payment):
	#get datetime object for last day of expiring month
	exp_date = payment['detail']['expires']
	month = int(exp_date[:2]) + 1
	exp_date = '%s%s' % (month, exp_date[2:])
	exp_date = datetime.strptime(exp_date, '%m/%Y')
	exp_date = exp_date - timedelta(1)
	exp_date = datetime.date(exp_date)

	now = datetime.now()
	now = datetime.date(now)

	if(now < exp_date):
		return False
	else:
		return True

def is_positive(amount):
	if(amount > 0):
		return True
	else:
		return False

def is_valid_patch(data):
	#update later for validating data for PATCH method
	return True

######################################################################
#   M A I N
######################################################################
if __name__ == '__main__':
	debug = (os.getenv('DEBUG', 'False') == 'True')
	port = os.getenv('PORT', '5000')
	app.run(host='0.0.0.0', port=int(port), debug=debug)
<|endoftext|>


<commit_before>from functools import wraps
import sys

from django.conf import settings
from django.db import connection

from huey import crontab
from huey import RedisHuey
from huey.utils import load_class

configuration_message = """
Configuring Huey for use with Django
====================================

Huey was designed to be simple to configure in the general case.  For that
reason, huey will "just work" with no configuration at all provided you have
Redis installed and running locally.

On the other hand, you can configure huey manually using the following
setting structure.

The following example uses Redis on localhost, and will run four worker
processes:

HUEY = {
    'name': 'my-app',
    'connection': {'host': 'localhost', 'port': 6379},
    'consumer': {
        'workers': 4,
        'worker_type': 'process',  # "thread" or "greenlet" are other options
    },
}

If you would like to configure Huey's logger using Django's integrated logging
settings, the logger used by consumer is named "huey.consumer".

Alternatively you can simply assign `settings.HUEY` to an actual `Huey`
object instance:

from huey import RedisHuey
HUEY = RedisHuey('my-app')
"""

def default_queue_name():
    try:
        return settings.DATABASE_NAME
    except AttributeError:
        try:
            return settings.DATABASES['default']['NAME']
        except KeyError:
            return 'huey'

def config_error(msg):
    print(configuration_message)
    print('\n\n')
    print(msg)
    sys.exit(1)

HUEY = getattr(settings, 'HUEY', None)
if HUEY is None:
    try:
        from huey import RedisHuey
    except ImportError:
        config_error('Error: Huey could not import the redis backend. '
                     'Install `redis-py`.')
    else:
        HUEY = RedisHuey(default_queue_name())

if isinstance(HUEY, dict):
    huey_config = HUEY.copy()  # Operate on a copy.
    name = huey_config.pop('name', default_queue_name())
    conn_kwargs = huey_config.pop('connection', {})
    try:
        del huey_config['consumer']  # Don't need consumer opts here.
    except KeyError:
        pass
    if 'always_eager' not in huey_config:
        huey_config['always_eager'] = settings.DEBUG
    huey_config.update(conn_kwargs)
    HUEY = RedisHuey(name, **huey_config)

task = HUEY.task
periodic_task = HUEY.periodic_task

def close_db(fn):
    """Decorator to be used with tasks that may operate on the database."""
    @wraps(fn)
    def inner(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        finally:
            connection.close()
    return inner

def db_task(*args, **kwargs):
    def decorator(fn):
        return task(*args, **kwargs)(close_db(fn))
    return decorator

def db_periodic_task(*args, **kwargs):
    def decorator(fn):
        return periodic_task(*args, **kwargs)(close_db(fn))
    return decorator
<commit_msg>Refs #146. Do not close Django db connection if `always_eager` is True. Thanks to @iivvoo for the comment.<commit_after>from functools import wraps
import sys

from django.conf import settings
from django.db import connection

from huey import crontab
from huey import RedisHuey
from huey.utils import load_class

configuration_message = """
Configuring Huey for use with Django
====================================

Huey was designed to be simple to configure in the general case.  For that
reason, huey will "just work" with no configuration at all provided you have
Redis installed and running locally.

On the other hand, you can configure huey manually using the following
setting structure.

The following example uses Redis on localhost, and will run four worker
processes:

HUEY = {
    'name': 'my-app',
    'connection': {'host': 'localhost', 'port': 6379},
    'consumer': {
        'workers': 4,
        'worker_type': 'process',  # "thread" or "greenlet" are other options
    },
}

If you would like to configure Huey's logger using Django's integrated logging
settings, the logger used by consumer is named "huey.consumer".

Alternatively you can simply assign `settings.HUEY` to an actual `Huey`
object instance:

from huey import RedisHuey
HUEY = RedisHuey('my-app')
"""

def default_queue_name():
    try:
        return settings.DATABASE_NAME
    except AttributeError:
        try:
            return settings.DATABASES['default']['NAME']
        except KeyError:
            return 'huey'

def config_error(msg):
    print(configuration_message)
    print('\n\n')
    print(msg)
    sys.exit(1)

HUEY = getattr(settings, 'HUEY', None)
if HUEY is None:
    try:
        from huey import RedisHuey
    except ImportError:
        config_error('Error: Huey could not import the redis backend. '
                     'Install `redis-py`.')
    else:
        HUEY = RedisHuey(default_queue_name())

if isinstance(HUEY, dict):
    huey_config = HUEY.copy()  # Operate on a copy.
    name = huey_config.pop('name', default_queue_name())
    conn_kwargs = huey_config.pop('connection', {})
    try:
        del huey_config['consumer']  # Don't need consumer opts here.
    except KeyError:
        pass
    if 'always_eager' not in huey_config:
        huey_config['always_eager'] = settings.DEBUG
    huey_config.update(conn_kwargs)
    HUEY = RedisHuey(name, **huey_config)

task = HUEY.task
periodic_task = HUEY.periodic_task

def close_db(fn):
    """Decorator to be used with tasks that may operate on the database."""
    @wraps(fn)
    def inner(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        finally:
            if not HUEY.always_eager:
                connection.close()
    return inner

def db_task(*args, **kwargs):
    def decorator(fn):
        return task(*args, **kwargs)(close_db(fn))
    return decorator

def db_periodic_task(*args, **kwargs):
    def decorator(fn):
        return periodic_task(*args, **kwargs)(close_db(fn))
    return decorator
<|endoftext|>