<commit_before># reversi.py
# Reversi (Othello)
"""
Reversi - a tile flipping game
An example from Chapter 15 of
'Invent Your Own Games With Python' by Al Sweigart
A.C. LoGreco
"""

import random
import sys

def drawBoard(board):
    """
    This function prints out the board that it was passed. Returns None.
    """
    HLINE = '  +---+---+---+---+---+---+---+---+'
    VLINE = '  |   |   |   |   |   |   |   |   |'

    print('    1   2   3   4   5   6   7   8')
    print(HLINE)
    for y in range(8):
        print(VLINE)
        print(y+1, end=' ')
        for x in range(8):
            print('| %s' % (board[x][y]), end=' ')
        print('|')
        print(VLINE)
        print(HLINE)

def resetBoard(board):
    """
    Blanks out the board it is passed, except for the original starting position.
    """
    for x in range(8):
        for y in range(8):
            board[x][y] = ' '

    # Starting pieces:
    board[3][3] = 'X'
    board[3][4] = 'O'
    board[4][3] = 'O'
    board[4][4] = 'X'

<commit_msg>Add getNewBoard() function to the reversi.py module.<commit_after># reversi.py
# Reversi (Othello)
"""
Reversi - a tile flipping game
An example from Chapter 15 of
'Invent Your Own Games With Python' by Al Sweigart
A.C. LoGreco
"""

import random
import sys

def drawBoard(board):
    """
    This function prints out the board that it was passed. Returns None.
    """
    HLINE = '  +---+---+---+---+---+---+---+---+'
    VLINE = '  |   |   |   |   |   |   |   |   |'

    print('    1   2   3   4   5   6   7   8')
    print(HLINE)
    for y in range(8):
        print(VLINE)
        print(y+1, end=' ')
        for x in range(8):
            print('| %s' % (board[x][y]), end=' ')
        print('|')
        print(VLINE)
        print(HLINE)

def resetBoard(board):
    """
    Blanks out the board it is passed, except for the original starting position.
    """
    for x in range(8):
        for y in range(8):
            board[x][y] = ' '

    # Starting pieces:
    board[3][3] = 'X'
    board[3][4] = 'O'
    board[4][3] = 'O'
    board[4][4] = 'X'

def getNewBoard():
    """
    Creates a brand new, blank board data structure.
    """
    board = []

    for i in range(8):
        board.append([' '] * 8)

    return board

<|endoftext|>


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

# This work was created by participants in the DataONE project, and is
# jointly copyrighted by participating institutions in DataONE. For
# more information on DataONE, see our web site at http://dataone.org.
#
#   Copyright 2009-2016 DataONE
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test serialization and de-serialization of the DataONEException
type.
"""

# Stdlib
import unittest
import xml.dom.minidom

# D1
from d1_common.types import exceptions

TRACE_SECTION = """  <traceInformation>
    <value>traceInformation0</value>
    <value>traceInformation2</value>
  </traceInformation>"""

VALID_ERROR_DOC = """<?xml version="1.0" encoding="UTF-8"?>
<error  detailCode="123.456.789"
        errorCode="456"
        identifier="SomeDataONEPID"
        name="IdentifierNotUnique"
        nodeId="urn:node:SomeNode">
  <description>description0</description>""" + TRACE_SECTION + """
</error>
"""

VALID_ERROR_DOC_NOTFOUND = """<?xml version="1.0" encoding="UTF-8"?>
<error detailCode="1800" errorCode="404" name="NotFound">
    <description>No system metadata could be found for given PID: something_bogus/</description>
</error>
"""

VALID_ERROR_DOC_NOTFOUND_2 = """<?xml version="1.0"?>
<error detailCode="0" errorCode="404" name="NotFound" nodeId="urn:node:LTER">
<description>Attempted to perform operation on non-existing object</description>
<traceInformation><value>1. something_bogus
2. on two lines</value></traceInformation>
</error>"""

VALID_ERROR_DOC_NOTFOUND_3 = """<?xml version="1.0"?>
<error detailCode="0" errorCode="404" name="NotFound" nodeId="urn:node:LTER">
<description>Attempted to perform operation on non-existing object</description>
<traceInformation><value>1. Σολυτα βωνορυμ θε κυο,
2. ναμ ετ νοσθερ σιμιλικυε.</value></traceInformation>
</error>"""

#  'SHA-1',
#  '3f56de593b6ffc536253b799b429453e3673fc19'
#)

# Missing detailCode.
INVALID_ERROR_DOC = (
  """<?xml version="1.0" encoding="UTF-8"?>
  <d1:error xmlns:d1="http://ns.dataone.org/service/types/exceptions"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://ns.dataone.org/service/types/exceptions"
  errorCode="0" name="IdentifierNotUnique" pid="somedataonepid">
  <description>description0</description>
  <traceInformation>traceInformation0</traceInformation>
  </d1:error>""", '', ''
)

class TestExceptions(unittest.TestCase):
  def test_100(self):
    """deserialize()"""
    d1_exception = exceptions.deserialize(VALID_ERROR_DOC)
    self.assertTrue(isinstance(d1_exception, exceptions.IdentifierNotUnique))
    self.assertEqual(d1_exception.detailCode, '123.456.789')
    self.assertEqual(d1_exception.errorCode, 409)
    self.assertEqual(d1_exception.name, 'IdentifierNotUnique')
    self.assertEqual(d1_exception.identifier, 'SomeDataONEPID')
    self.assertEqual(d1_exception.nodeId, 'urn:node:SomeNode')
    self.assertEqual(d1_exception.description, 'description0')
    self.assertEqual(d1_exception.traceInformation, TRACE_SECTION.strip())

  def test_110(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertTrue(isinstance(x2, exceptions.NotFound))
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_120(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND_2)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertTrue(isinstance(x2, exceptions.NotFound))
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_121(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND_3)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertTrue(isinstance(x2, exceptions.NotFound))
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_150(self):
    """deserialize() of bad document raises DataONEExceptionException"""
    self.assertRaises(
      exceptions.DataONEExceptionException, exceptions.deserialize,
      INVALID_ERROR_DOC[0]
    )

  def test_200(self):
    """String representation"""
    d1_exception = exceptions.deserialize(VALID_ERROR_DOC)
    self.assertTrue('name: IdentifierNotUnique' in str(d1_exception))
    self.assertTrue('errorCode: 409' in str(d1_exception))
    self.assertTrue('detailCode: 123.456.789' in str(d1_exception))

  def test_250(self):
    """create with only detailCode then serialize()"""
    e = exceptions.ServiceFailure(123)
    self.assertEqual(
      e.serialize(), u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123" errorCode="500" name="ServiceFailure"/>'
    )

  def test_260(self):
    """create with string detailCode and description, then serialize()"""
    e = exceptions.ServiceFailure('123.456.789', 'test description')
    se = e.serialize()
    self.assertEqual(
      se, u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123.456.789" errorCode="500" name="ServiceFailure">'
      u'<description>test description</description></error>'
    )

  def test_270(self):
    """create with detailCode, description and traceInformation, then serialize()"""
    e = exceptions.ServiceFailure(
      '123.456.789', description='test description',
      traceInformation='test traceInformation'
    )
    se = e.serialize()
    self.assertEqual(
      se, u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123.456.789" errorCode="500" name="ServiceFailure">'
      u'<description>test description</description>'
      u'<traceInformation>test traceInformation</traceInformation></error>'
    )

  def test_280(self):
    """serialize_to_headers()"""
    e = exceptions.ServiceFailure(
      '123.456.789', 'test description', 'test traceInformation'
    )
    header_dict = e.serialize_to_headers()
    expected_dict = {
      'DataONE-Exception-TraceInformation': u'test traceInformation',
      'DataONE-Exception-DetailCode': u'123.456.789',
      'DataONE-Exception-Name': 'ServiceFailure',
      'DataONE-Exception-Description': u'test description',
      'DataONE-Exception-NodeID': '',
      'DataONE-Exception-Identifier': '',
      'DataONE-Exception-ErrorCode': u'500'
    }
    self.assertDictEqual(header_dict, expected_dict)

  def test_300(self):
    """deserialize_from_headers()"""
    headers = {
      'DataONE-Exception-Name': 'IdentifierNotUnique', # required
      'DataONE-Exception-DetailCode': '123.456.789', # required
      'DataONE-Exception-Description':
        'test description', # provided but not required
      'dataone-exception-traceinformation':
        'test traceInformation', # not required but provided in lower case
      #'DataONE-Exception-Identifier' not required or provided
      #'DataONE-Exception-NodeId' not required or provided
    }
    e = exceptions.deserialize_from_headers(headers)
    self.assertEqual(e.name, 'IdentifierNotUnique')
    self.assertEqual(e.errorCode, 409)
    self.assertEqual(e.detailCode, '123.456.789')
    self.assertEqual(e.description, 'test description')
    self.assertEqual(e.traceInformation, 'test traceInformation')

  def test_400(self):
    """Test serialization and deserialization of DataONE Exceptions

    Test serialization and deserialization of DataONE Exceptions by performing
    a round trip:

    1) Create a native DataONE Exception object.
    2) Serialize the object to XML.
    3) Deserialize XML to object.
    4) Verify that the object contains the same information as in (1).
    """
    # Create a native DataONE IdentifierNotUnique Exception object.
    exc = exceptions.IdentifierNotUnique(
      1010, 'description_test', 'test trace information', 'test_pid', 'node_id'
    )
    # Serialize to XML.
    exc_ser_xml = exc.serialize()
    #print exc_ser_xml
    # Check XML.
    dom = xml.dom.minidom.parseString(exc_ser_xml)
    root = dom.firstChild
    self.assertEqual(root.tagName, u'error')
    self.assertEqual(root.attributes['detailCode'].value, u'1010')
    self.assertEqual(root.attributes['errorCode'].value, u'409')
    self.assertEqual(root.attributes['name'].value, u'IdentifierNotUnique')
    self.assertEqual(root.attributes['identifier'].value, u'test_pid')
    self.assertEqual(
      root.getElementsByTagName('description')[0].childNodes[0].nodeValue,
      u'description_test'
    )
    # Disabled until we have decided how to encode traceInformation.
    #self.assertEqual(root.getElementsByTagName('traceInformation')[0]\
    #                 .childNodes[0].nodeValue, u'test trace information')
    # Deserialize XML.
    exc_deser = exceptions.deserialize(exc_ser_xml)
    # Check deserialized native object.
    self.assertEqual(exc_deser.detailCode, '1010')
    self.assertEqual(exc_deser.errorCode, 409)
    self.assertEqual(exc_deser.name, 'IdentifierNotUnique')
    self.assertEqual(exc_deser.identifier, 'test_pid')
    self.assertEqual(exc_deser.description, 'description_test')
    # Disabled until we have decided how to encode traceInformation.
    #self.assertEqual(exc_deser.traceInformation, 'test trace information')
<commit_msg>Fix tests for D1 exceptions<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This work was created by participants in the DataONE project, and is
# jointly copyrighted by participating institutions in DataONE. For
# more information on DataONE, see our web site at http://dataone.org.
#
#   Copyright 2009-2016 DataONE
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test serialization and de-serialization of the DataONEException
type.
"""

# Stdlib
import unittest
import xml.dom.minidom

# D1
from d1_common.types import exceptions

TRACE_SECTION = """  <traceInformation>
    <value>traceInformation0</value>
    <value>traceInformation2</value>
  </traceInformation>"""

VALID_ERROR_DOC = """<?xml version="1.0" encoding="UTF-8"?>
<error  detailCode="123.456.789"
        errorCode="456"
        identifier="SomeDataONEPID"
        name="IdentifierNotUnique"
        nodeId="urn:node:SomeNode">
  <description>description0</description>""" + TRACE_SECTION + """
</error>
"""

VALID_ERROR_DOC_NOTFOUND = """<?xml version="1.0" encoding="UTF-8"?>
<error detailCode="1800" errorCode="404" name="NotFound">
    <description>No system metadata could be found for given PID: something_bogus/</description>
</error>
"""

VALID_ERROR_DOC_NOTFOUND_2 = """<?xml version="1.0"?>
<error detailCode="0" errorCode="404" name="NotFound" nodeId="urn:node:LTER">
<description>Attempted to perform operation on non-existing object</description>
<traceInformation><value>1. something_bogus
2. on two lines</value></traceInformation>
</error>"""

VALID_ERROR_DOC_NOTFOUND_3 = """<?xml version="1.0"?>
<error detailCode="0" errorCode="404" name="NotFound" nodeId="urn:node:LTER">
<description>Attempted to perform operation on non-existing object</description>
<traceInformation><value>1. Σολυτα βωνορυμ θε κυο,
2. ναμ ετ νοσθερ σιμιλικυε.</value></traceInformation>
</error>"""

#  'SHA-1',
#  '3f56de593b6ffc536253b799b429453e3673fc19'
#)

# Missing detailCode.
INVALID_ERROR_DOC = (
  """<?xml version="1.0" encoding="UTF-8"?>
  <d1:error xmlns:d1="http://ns.dataone.org/service/types/exceptions"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://ns.dataone.org/service/types/exceptions"
  errorCode="0" name="IdentifierNotUnique" pid="somedataonepid">
  <description>description0</description>
  <traceInformation>traceInformation0</traceInformation>
  </d1:error>""", '', ''
)

class TestExceptions(unittest.TestCase):
  def test_100(self):
    """deserialize()"""
    d1_exception = exceptions.deserialize(VALID_ERROR_DOC)
    self.assertIsInstance(d1_exception, exceptions.IdentifierNotUnique)
    self.assertEqual(d1_exception.detailCode, '123.456.789')
    self.assertEqual(d1_exception.errorCode, 409)
    self.assertEqual(d1_exception.name, 'IdentifierNotUnique')
    self.assertEqual(d1_exception.identifier, 'SomeDataONEPID')
    self.assertEqual(d1_exception.nodeId, 'urn:node:SomeNode')
    self.assertEqual(d1_exception.description, 'description0')
    self.assertEqual(d1_exception.traceInformation, TRACE_SECTION.strip())

  def test_110(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertIsInstance(x2, exceptions.NotFound)
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_120(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND_2)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertIsInstance(x2, exceptions.NotFound)
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_121(self):
    """deserialize, serialize, deserialize"""
    x1 = exceptions.deserialize(VALID_ERROR_DOC_NOTFOUND_3)
    sxml = x1.serialize()
    x2 = exceptions.deserialize(sxml)
    self.assertIsInstance(x2, exceptions.NotFound)
    self.assertEqual(x1.errorCode, x2.errorCode)
    self.assertEqual(x1.detailCode, x2.detailCode)
    self.assertEqual(x1.name, x2.name)
    self.assertEqual(x1.description, x2.description)
    self.assertEqual(x1.nodeId, x2.nodeId)
    self.assertEqual(x1.identifier, x2.identifier)
    self.assertEqual(x1.traceInformation, x2.traceInformation)

  def test_150(self):
    """deserialize() of bad document raises ServiceFailure"""
    self.assertRaises(
      exceptions.ServiceFailure, exceptions.deserialize, INVALID_ERROR_DOC[0]
    )

  def test_200(self):
    """String representation"""
    d1_exception = exceptions.deserialize(VALID_ERROR_DOC)
    self.assertTrue('name: IdentifierNotUnique' in str(d1_exception))
    self.assertTrue('errorCode: 409' in str(d1_exception))
    self.assertTrue('detailCode: 123.456.789' in str(d1_exception))

  def test_250(self):
    """create with only detailCode then serialize()"""
    e = exceptions.ServiceFailure(123)
    self.assertEqual(
      e.serialize(), u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123" errorCode="500" name="ServiceFailure"/>'
    )

  def test_260(self):
    """create with string detailCode and description, then serialize()"""
    e = exceptions.ServiceFailure('123.456.789', 'test description')
    se = e.serialize()
    self.assertEqual(
      se, u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123.456.789" errorCode="500" name="ServiceFailure">'
      u'<description>test description</description></error>'
    )

  def test_270(self):
    """create with detailCode, description and traceInformation, then serialize()"""
    e = exceptions.ServiceFailure(
      '123.456.789', description='test description',
      traceInformation='test traceInformation'
    )
    se = e.serialize()
    self.assertEqual(
      se, u'<?xml version="1.0" encoding="utf-8"?>'
      u'<error detailCode="123.456.789" errorCode="500" name="ServiceFailure">'
      u'<description>test description</description>'
      u'<traceInformation>test traceInformation</traceInformation></error>'
    )

  def test_280(self):
    """serialize_to_headers()"""
    e = exceptions.ServiceFailure(
      '123.456.789', 'test description', 'test traceInformation'
    )
    header_dict = e.serialize_to_headers()
    expected_dict = {
      'DataONE-Exception-TraceInformation': u'test traceInformation',
      'DataONE-Exception-DetailCode': u'123.456.789',
      'DataONE-Exception-Name': 'ServiceFailure',
      'DataONE-Exception-Description': u'test description',
      'DataONE-Exception-NodeID': '',
      'DataONE-Exception-Identifier': '',
      'DataONE-Exception-ErrorCode': u'500'
    }
    self.assertDictEqual(header_dict, expected_dict)

  def test_300(self):
    """deserialize_from_headers()"""
    headers = {
      'DataONE-Exception-Name': 'IdentifierNotUnique', # required
      'DataONE-Exception-DetailCode': '123.456.789', # required
      'DataONE-Exception-Description':
        'test description', # provided but not required
      'dataone-exception-traceinformation':
        'test traceInformation', # not required but provided in lower case
      #'DataONE-Exception-Identifier' not required or provided
      #'DataONE-Exception-NodeId' not required or provided
    }
    e = exceptions.deserialize_from_headers(headers)
    self.assertEqual(e.name, 'IdentifierNotUnique')
    self.assertEqual(e.errorCode, 409)
    self.assertEqual(e.detailCode, '123.456.789')
    self.assertEqual(e.description, 'test description')
    self.assertEqual(e.traceInformation, 'test traceInformation')

  def test_400(self):
    """Test serialization and deserialization of DataONE Exceptions

    Test serialization and deserialization of DataONE Exceptions by performing
    a round trip:

    1) Create a native DataONE Exception object.
    2) Serialize the object to XML.
    3) Deserialize XML to object.
    4) Verify that the object contains the same information as in (1).
    """
    # Create a native DataONE IdentifierNotUnique Exception object.
    exc = exceptions.IdentifierNotUnique(
      1010, 'description_test', 'test trace information', 'test_pid', 'node_id'
    )
    # Serialize to XML.
    exc_ser_xml = exc.serialize()
    #print exc_ser_xml
    # Check XML.
    dom = xml.dom.minidom.parseString(exc_ser_xml)
    root = dom.firstChild
    self.assertEqual(root.tagName, u'error')
    self.assertEqual(root.attributes['detailCode'].value, u'1010')
    self.assertEqual(root.attributes['errorCode'].value, u'409')
    self.assertEqual(root.attributes['name'].value, u'IdentifierNotUnique')
    self.assertEqual(root.attributes['identifier'].value, u'test_pid')
    self.assertEqual(
      root.getElementsByTagName('description')[0].childNodes[0].nodeValue,
      u'description_test'
    )
    # Disabled until we have decided how to encode traceInformation.
    #self.assertEqual(root.getElementsByTagName('traceInformation')[0]\
    #                 .childNodes[0].nodeValue, u'test trace information')
    # Deserialize XML.
    exc_deser = exceptions.deserialize(exc_ser_xml)
    # Check deserialized native object.
    self.assertEqual(exc_deser.detailCode, '1010')
    self.assertEqual(exc_deser.errorCode, 409)
    self.assertEqual(exc_deser.name, 'IdentifierNotUnique')
    self.assertEqual(exc_deser.identifier, 'test_pid')
    self.assertEqual(exc_deser.description, 'description_test')
    # Disabled until we have decided how to encode traceInformation.
    #self.assertEqual(exc_deser.traceInformation, 'test trace information')
<|endoftext|>


<commit_before># Specifically determine input http://stackoverflow.com/questions/26082234
from mrjob.job import MRJob
from mrjob.step import MRStep
from collections import Counter
import itertools
import time
start_time = time.time()

s        = 100 # set support threshold
topN     = 15  # set top items to show

class MRProductRecommendation(MRJob):

  def mapper_parse_line(self, _, line):
    items  = line.split()
    single = [ ( item, [ ( item, 'Total') ] )  for item in items  ]
    pairs  = [ ( pair[0], [ pair ] ) for pair in itertools.permutations(items, 2) ]
    return single + pairs

  def reducer_groupByKey(self, key, values):   #groupByKey()
    yield key, list(itertools.chain(*values))  #yield key, reduce(lambda a, b: a + b, values)

  def mapper_aggregate_tops(self, key, all_values):
    items = [ pair[1] for pair in all_values ]
    topCounter = Counter(items)
    total = topCounter['Total']
    if total > s:
      del( topCounter['Total'] )
      topNarray = topCounter.most_common( topN )
      topNarray.append( ('Total', total) ) #so the count of single item will be always at the end.
      yield key, topNarray

  def mapper_store_counters(self, k1, topNarray):
    total = float( topNarray.pop(-1)[1] )
    local_counter = Counter()
    for k2, count in topNarray:
      local_counter[ (k1, k2) ] = count/total
    yield k1, local_counter.most_common( topN )

  def reducer_maxN(self, _, topNarray):
    combined = reduce( lambda a, b: a + b, topNarray )
    yield None, Counter( dict((tuple(pair), count) for pair, count in combined) ).most_common( topN )

  def steps(self):
    return [
        MRStep(mapper=self.mapper_parse_line,
               reducer=self.reducer_groupByKey),
        MRStep(mapper=self.mapper_aggregate_tops),
        MRStep(mapper=self.mapper_store_counters,
               combiner=self.reducer_maxN,
               reducer=self.reducer_maxN )    ]

if __name__ == '__main__':
    MRProductRecommendation.run()

print("--- %s seconds ---" % (time.time() - start_time))<commit_msg>add comments for .takeOrdered()<commit_after># Specifically determine input http://stackoverflow.com/questions/26082234
from mrjob.job import MRJob
from mrjob.step import MRStep
from collections import Counter
import itertools
import time
start_time = time.time()

s        = 100 # set support threshold
topN     = 15  # set top items to show

class MRProductRecommendation(MRJob):

  def mapper_parse_line(self, _, line):
    items  = line.split()
    single = [ ( item, [ ( item, 'Total') ] )  for item in items  ]
    pairs  = [ ( pair[0], [ pair ] ) for pair in itertools.permutations(items, 2) ]
    return single + pairs

  def reducer_groupByKey(self, key, values):   #groupByKey()
    yield key, list(itertools.chain(*values))  #yield key, reduce(lambda a, b: a + b, values)

  def mapper_aggregate_tops(self, key, all_values):
    items = [ pair[1] for pair in all_values ]
    topCounter = Counter( items )
    total = topCounter['Total']
    if total > s:
      del( topCounter['Total'] )
      topNarray = topCounter.most_common( topN )
      topNarray.append( ('Total', total) ) #so the count of single item will be always at the end.
      yield key, topNarray

  def mapper_store_counters(self, k1, topNarray):
    total = float( topNarray.pop(-1)[1] )
    local_counter = Counter()
    for k2, count in topNarray:
      local_counter[ (k1, k2) ] = count / total
    yield k1, local_counter.most_common( topN )

  def reducer_maxN(self, _, topNarray): #use both reducer and combiner for #takeOrdered()
    combined = reduce( lambda a, b: a + b, topNarray )
    yield None, Counter( dict((tuple(pair), count) for pair, count in combined) ).most_common( topN )

  def steps(self):
    return [
        MRStep(mapper=self.mapper_parse_line,
               reducer=self.reducer_groupByKey),
        MRStep(mapper=self.mapper_aggregate_tops),
        MRStep(mapper=self.mapper_store_counters,
               combiner=self.reducer_maxN,
               reducer=self.reducer_maxN )    ]

if __name__ == '__main__':
    MRProductRecommendation.run()

print("--- %s seconds ---" % (time.time() - start_time))<|endoftext|>


<commit_before>from django.db import models

from waldur_core.core.managers import GenericKeyMixin, SummaryQuerySet

def get_permission_subquery(permissions, user):
    subquery = models.Q()
    for entity in ('customer', 'project'):
        path = getattr(permissions, '%s_path' % entity, None)
        if not path:
            continue

        if path == 'self':
            prefix = 'permissions__'
        else:
            prefix = path + '__permissions__'

        kwargs = {
            prefix + 'user': user,
            prefix + 'is_active': True
        }

        subquery |= models.Q(**kwargs)

    # Add extra query which basically allows to
    # additionally filter by some flag and ignore permissions
    extra_query = getattr(permissions, 'extra_query', None)
    if extra_query:
        subquery |= models.Q(**extra_query)

    return subquery

def filter_queryset_for_user(queryset, user):
    if not queryset:
        return queryset

    if user is None or user.is_staff or user.is_support:
        return queryset

    permissions = getattr(queryset.model, 'Permissions', None)
    if not permissions:
        return queryset

    subquery = get_permission_subquery(permissions, user)
    if not subquery:
        return queryset

    return queryset.filter(subquery).distinct()

class StructureQueryset(models.QuerySet):
    """ Provides additional filtering by customer or project (based on permission definition).

        Example:

            .. code-block:: python

                Instance.objects.filter(project=12)

                Droplet.objects.filter(
                    customer__name__startswith='A',
                    state=Droplet.States.ONLINE)

                Droplet.objects.filter(Q(customer__name='Alice') | Q(customer__name='Bob'))
    """

    def exclude(self, *args, **kwargs):
        return super(StructureQueryset, self).exclude(
            *[self._patch_query_argument(a) for a in args],
            **self._filter_by_custom_fields(**kwargs))

    def filter(self, *args, **kwargs):
        return super(StructureQueryset, self).filter(
            *[self._patch_query_argument(a) for a in args],
            **self._filter_by_custom_fields(**kwargs))

    def _patch_query_argument(self, arg):
        # patch Q() objects if passed and add support of custom fields
        if isinstance(arg, models.Q):
            children = []
            for opt in arg.children:
                if isinstance(opt, models.Q):
                    children.append(self._patch_query_argument(opt))
                else:
                    args = self._filter_by_custom_fields(**dict([opt]))
                    children.append(tuple(args.items())[0])
            arg.children = children
        return arg

    def _filter_by_custom_fields(self, **kwargs):
        # traverse over filter arguments in search of custom fields
        args = {}
        fields = [f.name for f in self.model._meta.get_fields()]
        for field, val in kwargs.items():
            base_field = field.split('__')[0]
            if base_field in fields:
                args.update(**{field: val})
            elif base_field in ('customer', 'project'):
                args.update(self._filter_by_permission_fields(base_field, field, val))
            else:
                args.update(**{field: val})

        return args

    def _filter_by_permission_fields(self, name, field, value):
        # handle fields connected via permissions relations
        extra = '__'.join(field.split('__')[1:]) if '__' in field else None
        try:
            # look for the target field path in Permissions class,
            path = getattr(self.model.Permissions, '%s_path' % name)
        except AttributeError:
            # fallback to FieldError if it's missed
            return {field: value}
        else:
            if path == 'self':
                if extra:
                    return {extra: value}
                else:
                    return {'pk': value.pk if isinstance(value, models.Model) else value}
            else:
                if extra:
                    path += '__' + extra
                return {path: value}

StructureManager = models.Manager.from_queryset(StructureQueryset)

class ResourceSummaryQuerySet(SummaryQuerySet):
    # Hack for permissions
    @property
    def model(self):
        from waldur_core.structure.models import ResourceMixin
        return ResourceMixin

class ServiceSummaryQuerySet(SummaryQuerySet):
    # Hack for permissions
    @property
    def model(self):
        from waldur_core.structure.models import Service
        return Service

class ServiceSettingsManager(GenericKeyMixin, models.Manager):
    """ Allows to filter and get service settings by generic key """

    def get_available_models(self):
        """ Return list of models that are acceptable """
        from waldur_core.structure.models import ResourceMixin
        return ResourceMixin.get_all_models()

class SharedServiceSettingsManager(ServiceSettingsManager):
    def get_queryset(self):
        return super(SharedServiceSettingsManager, self).get_queryset().filter(shared=True)

class PrivateServiceSettingsManager(ServiceSettingsManager):
    def get_queryset(self):
        return super(PrivateServiceSettingsManager, self).get_queryset().filter(shared=False)
<commit_msg>Skip extra database query.<commit_after>from django.db import models

from waldur_core.core.managers import GenericKeyMixin, SummaryQuerySet

def get_permission_subquery(permissions, user):
    subquery = models.Q()
    for entity in ('customer', 'project'):
        path = getattr(permissions, '%s_path' % entity, None)
        if not path:
            continue

        if path == 'self':
            prefix = 'permissions__'
        else:
            prefix = path + '__permissions__'

        kwargs = {
            prefix + 'user': user,
            prefix + 'is_active': True
        }

        subquery |= models.Q(**kwargs)

    # Add extra query which basically allows to
    # additionally filter by some flag and ignore permissions
    extra_query = getattr(permissions, 'extra_query', None)
    if extra_query:
        subquery |= models.Q(**extra_query)

    return subquery

def filter_queryset_for_user(queryset, user):
    if user is None or user.is_staff or user.is_support:
        return queryset

    try:
        permissions = queryset.model.Permissions
    except AttributeError:
        return queryset

    subquery = get_permission_subquery(permissions, user)
    if not subquery:
        return queryset

    return queryset.filter(subquery).distinct()

class StructureQueryset(models.QuerySet):
    """ Provides additional filtering by customer or project (based on permission definition).

        Example:

            .. code-block:: python

                Instance.objects.filter(project=12)

                Droplet.objects.filter(
                    customer__name__startswith='A',
                    state=Droplet.States.ONLINE)

                Droplet.objects.filter(Q(customer__name='Alice') | Q(customer__name='Bob'))
    """

    def exclude(self, *args, **kwargs):
        return super(StructureQueryset, self).exclude(
            *[self._patch_query_argument(a) for a in args],
            **self._filter_by_custom_fields(**kwargs))

    def filter(self, *args, **kwargs):
        return super(StructureQueryset, self).filter(
            *[self._patch_query_argument(a) for a in args],
            **self._filter_by_custom_fields(**kwargs))

    def _patch_query_argument(self, arg):
        # patch Q() objects if passed and add support of custom fields
        if isinstance(arg, models.Q):
            children = []
            for opt in arg.children:
                if isinstance(opt, models.Q):
                    children.append(self._patch_query_argument(opt))
                else:
                    args = self._filter_by_custom_fields(**dict([opt]))
                    children.append(tuple(args.items())[0])
            arg.children = children
        return arg

    def _filter_by_custom_fields(self, **kwargs):
        # traverse over filter arguments in search of custom fields
        args = {}
        fields = [f.name for f in self.model._meta.get_fields()]
        for field, val in kwargs.items():
            base_field = field.split('__')[0]
            if base_field in fields:
                args.update(**{field: val})
            elif base_field in ('customer', 'project'):
                args.update(self._filter_by_permission_fields(base_field, field, val))
            else:
                args.update(**{field: val})

        return args

    def _filter_by_permission_fields(self, name, field, value):
        # handle fields connected via permissions relations
        extra = '__'.join(field.split('__')[1:]) if '__' in field else None
        try:
            # look for the target field path in Permissions class,
            path = getattr(self.model.Permissions, '%s_path' % name)
        except AttributeError:
            # fallback to FieldError if it's missed
            return {field: value}
        else:
            if path == 'self':
                if extra:
                    return {extra: value}
                else:
                    return {'pk': value.pk if isinstance(value, models.Model) else value}
            else:
                if extra:
                    path += '__' + extra
                return {path: value}

StructureManager = models.Manager.from_queryset(StructureQueryset)

class ResourceSummaryQuerySet(SummaryQuerySet):
    # Hack for permissions
    @property
    def model(self):
        from waldur_core.structure.models import ResourceMixin
        return ResourceMixin

class ServiceSummaryQuerySet(SummaryQuerySet):
    # Hack for permissions
    @property
    def model(self):
        from waldur_core.structure.models import Service
        return Service

class ServiceSettingsManager(GenericKeyMixin, models.Manager):
    """ Allows to filter and get service settings by generic key """

    def get_available_models(self):
        """ Return list of models that are acceptable """
        from waldur_core.structure.models import ResourceMixin
        return ResourceMixin.get_all_models()

class SharedServiceSettingsManager(ServiceSettingsManager):
    def get_queryset(self):
        return super(SharedServiceSettingsManager, self).get_queryset().filter(shared=True)

class PrivateServiceSettingsManager(ServiceSettingsManager):
    def get_queryset(self):
        return super(PrivateServiceSettingsManager, self).get_queryset().filter(shared=False)
<|endoftext|>


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

# Author: Tom Lambert
# Content: Main program for tasks in ab5.py

from decimal import Decimal
from kreis import Kreis

def main():
    # Calculated with Mathematica (see Matheamtica.nb) to a precision of 100 places behind decimal point
    angles = {
        0: (Decimal("1.0"), Decimal("0.0")),
        10: (Decimal("0.98480775301220805936674302458952301367064325171984"
                     "24187900257523558275999430362392746784100561198992"),
             Decimal("0.17364817766693034885171662676931479600037567718406"
                     "93872362413781320658221390147354215166131573995740")),
        22: (Decimal("0.92718385456678740080647445113695694209762171984899"
                     "76151430209124095628534066347424128493580393263935"),
             Decimal("0.37460659341591203541496377450119513100015892225367"
                     "61741034403710333586143660852189586357362224852295")),
        23: (Decimal("0.92050485345244032739689472330046142027950328097024"
                     "03012627017117829537900873103657545739776622661136"),
             Decimal("0.39073112848927375506208458888909426761801516757643"
                     "20757471065494645546820718925532166282293840540004")),
        45: (Decimal("0.70710678118654752440084436210484903928483593768847"
                     "40365883398689953662392310535194251937671638207864"),
             Decimal("0.70710678118654752440084436210484903928483593768847"
                     "40365883398689953662392310535194251937671638207864")),
        90: (Decimal("0.0"), Decimal("1.0")),
        280: (Decimal("0.17364817766693034885171662676931479600037567718406"
                      "93872362413781320658221390147354215166131573995740"),
              Decimal("-0.98480775301220805936674302458952301367064325171984"
                      "24187900257523558275999430362392746784100561198992")),
        359: (Decimal("0.99984769515639123915701155881391485169274031058318"
                      "59396583207145115391811033372153972993952881103455"),
              Decimal("-0.0174524064372835128194189785163161924722527203071"
                      "3964268361242764059738420392807004200192679102134691"))
    }

    k = Kreis()

    k.reset_function_call_counter()
    n = k.naiv()
    print("Anzahl der Aufrufe von sin oder cos in naiv(): {0}".format(k.function_call_counter))

    k.reset_function_call_counter()
    e = k.effizient()
    print("Anzahl der Aufrufe von sin oder cos in effizient(): {0}".format(k.function_call_counter))

    k.reset_function_call_counter()
    s = k.symmetrie()
    print("Anzahl der Aufrufe von sin oder cos in symmetrie(): {0}".format(k.function_call_counter))

    for angle in angles:
        print("Vergleich")

main()
<commit_msg>Added Output and tests<commit_after>#!/usr/bin/env python

# Author: Tom Lambert
# Content: Main program for tasks in ab5.py

from kreis import Kreis
from decimal import Decimal
from numpy as np

def main():
    """
    The main function of this program.
    :return: Nothing.
    """

    Decimal.getcontext().prec = 100

    # Calculated with Mathematica (see Matheamtica.nb) to a precision of 100 places behind decimal point
    angles = {
        0:   (Decimal("1.0"),
              Decimal("0.0")),
        10:  (Decimal("0.98480775301220805936674302458952301367064325171984"
                      "24187900257523558275999430362392746784100561198992"),
              Decimal("0.17364817766693034885171662676931479600037567718406"
                      "93872362413781320658221390147354215166131573995740")),
        22:  (Decimal("0.92718385456678740080647445113695694209762171984899"
                      "76151430209124095628534066347424128493580393263935"),
              Decimal("0.37460659341591203541496377450119513100015892225367"
                      "61741034403710333586143660852189586357362224852295")),
        23:  (Decimal("0.92050485345244032739689472330046142027950328097024"
                      "03012627017117829537900873103657545739776622661136"),
              Decimal("0.39073112848927375506208458888909426761801516757643"
                      "20757471065494645546820718925532166282293840540004")),
        45:  (Decimal("0.70710678118654752440084436210484903928483593768847"
                      "40365883398689953662392310535194251937671638207864"),
              Decimal("0.70710678118654752440084436210484903928483593768847"
                      "40365883398689953662392310535194251937671638207864")),
        90:  (Decimal("0.0"),
              Decimal("1.0")),
        280: (Decimal("0.17364817766693034885171662676931479600037567718406"
                      "93872362413781320658221390147354215166131573995740"),
              Decimal("-0.98480775301220805936674302458952301367064325171984"
                      "24187900257523558275999430362392746784100561198992")),
        359: (Decimal("0.99984769515639123915701155881391485169274031058318"
                      "59396583207145115391811033372153972993952881103455"),
              Decimal("-0.0174524064372835128194189785163161924722527203071"
                      "3964268361242764059738420392807004200192679102134691"))
    }

    k = Kreis()

    print("This program compares different ways to calculate the points at the unit circle.")
    print("For more information about the algorithms, see EWR/ab5 document.")
    print()

    print("The points for 360 angles will be calculated...")

    k.reset_function_call_counter()
    n = k.naiv()
    print("Number of calls of sin or cos in naiv(): {0}".format(k.function_call_counter))

    k.reset_function_call_counter()
    e = k.effizient()
    print("Number of calls of sin or cos in effizient(): {0}".format(k.function_call_counter))

    k.reset_function_call_counter()
    s = k.symmetrie()
    print("Number of calls of sin or cos in symmetrie(): {0}".format(k.function_call_counter))

    print("All points were calculated.")
    print()
    print("Some calculated points will be compared to more exact calculated values.")
    print()

    for angle in angles:
        print("Compare of exactness with an angle of {0}".format(angle))
        print("x/y calculated with Mathematica with 100 places behind decimal point:")
        print("m_x: {0}".format(angles[angle][0]))
        print("m_y: {0}".format(angles[angle][1]))
        print()

        print("Calculated with naiv():")
        print("n_x: {0}".format(n[angle][0]))
        print("n_y: {0}".format(n[angle][1]))
        print("Absolute approximation error from m_x/m_y:")
        print("|m_x - n_x| = {0}".format(np.abs(n[angle][0] - angles[angle][0])))
        print("|m_x - n_x| = {0}".format(np.abs(n[angle][0] - angles[angle][0])))
        print("Relative approximation error from m_x/m_y:")
        print("|(m_x - n_x)/m_x| = {0}".format(np.abs((n[angle][0] - angles[angle][0]) / n[angle][0])))
        print("|(m_y - n_y)/m_y| = {0}".format(np.abs((n[angle][1] - angles[angle][1]) / n[angle][1])))
        print("|(m_x - n_x)/n_x| = {0}".format(np.abs((n[angle][0] - angles[angle][0]) / angles[angle][0])))
        print("|(m_y - n_y)/n_y| = {0}".format(np.abs((n[angle][1] - angles[angle][1]) / angles[angle][1])))
        print()

        print("Calculated with effizient():")
        print("e_x: {0}".format(e[angle][0]))
        print("e_y: {0}".format(e[angle][1]))
        print("Absolute approximation error from m_x/m_y:")
        print("|m_x - e_x| = {0}".format(np.abs(e[angle][0] - angles[angle][0])))
        print("|m_x - e_x| = {0}".format(np.abs(e[angle][0] - angles[angle][0])))
        print("Relative approximation error from m_x/m_y:")
        print("|(m_x - e_x)/m_x| = {0}".format(np.abs((e[angle][0] - angles[angle][0]) / e[angle][0])))
        print("|(m_y - e_y)/m_y| = {0}".format(np.abs((e[angle][1] - angles[angle][1]) / e[angle][1])))
        print("|(m_x - e_x)/n_x| = {0}".format(np.abs((e[angle][0] - angles[angle][0]) / angles[angle][0])))
        print("|(m_y - e_y)/n_y| = {0}".format(np.abs((e[angle][1] - angles[angle][1]) / angles[angle][1])))
        print()

        print("Calculated with symmetrie():")
        print("s_x: {0}".format(s[angle][0]))
        print("s_y: {0}".format(s[angle][1]))
        print("Absolute approximation error from m_x/m_y:")
        print("|m_x - s_x| = {0}".format(np.abs(s[angle][0] - angles[angle][0])))
        print("|m_x - s_x| = {0}".format(np.abs(s[angle][0] - angles[angle][0])))
        print("Relative approximation error from m_x/m_y:")
        print("|(m_x - s_x)/m_x| = {0}".format(np.abs((s[angle][0] - angles[angle][0]) / s[angle][0])))
        print("|(m_y - s_y)/m_y| = {0}".format(np.abs((s[angle][1] - angles[angle][1]) / s[angle][1])))
        print("|(m_x - s_x)/n_x| = {0}".format(np.abs((s[angle][0] - angles[angle][0]) / angles[angle][0])))
        print("|(m_y - s_y)/n_y| = {0}".format(np.abs((s[angle][1] - angles[angle][1]) / angles[angle][1])))
        print()
        print("---------------------------------------------------------------------------")
        print()

    print("All tests run")

# always execute main(), because no user input is required
main()
<|endoftext|>


<commit_before>from django.conf.urls import patterns, include, url

urlpatterns = patterns('',

    # registration
    url(r'^accounts/', include('auth.urls')),

    # documents
    url(r'^', include('documents.urls')),

)
<commit_msg>activated admin interface<commit_after>from django.conf.urls import patterns, include, url
from django.contrib import admin

urlpatterns = patterns('',

    # registration
    url(r'^accounts/', include('auth.urls')),

    # documents
    url(r'^', include('documents.urls')),

    # admin
    url(r'^admin/', include(admin.site.urls)),

)
<|endoftext|>


<commit_before># encoding: utf-8

import warnings

if __debug__:
	from collections import deque

from functools import partial
from inspect import isclass, ismethod

from .exc import InvalidMethod

log = __import__('logging').getLogger(__name__)

def invalid_method(*args, **kw):
	raise InvalidMethod()

class ResourceDispatch(object):
	__slots__ = ()

	def __repr__(self):
		return "ResourceDispatch(0x{id})".format(id=id(self), self=self)

	def __call__(self, context, obj, path):
		verb = getattr(context, 'environ', context)['REQUEST_METHOD'].lower() if context else 'get'

		if __debug__:
			if not isinstance(path, deque):
				warnings.warn(
						"Your code is not providing the path as a deque; this will be cast in development but"
						"will explode gloriously if run in a production environment.",
						RuntimeWarning, stacklevel=1
					)

				if isinstance(path, str):
					path = deque(path.split('/')[1 if not path or path.startswith('/') else 0:])
				else:
					path = deque(path)

			log.debug("Preparing resource dispatch. " + repr(obj), extra=dict(
					dispatcher = repr(self),
					context = repr(context),
					obj = repr(obj),
					path = list(path),
					verb = verb,
				))

		if isclass(obj):
			obj = obj(context, None, None)
			yield None, obj, False  # Announce class instantiation.

		consumed = None
		Resource = getattr(obj, '__resource__', None)
		safe = {i for i in dir(obj) if i[0] != '_'} | {'options'}
		if 'get' in safe: safe.add('head')

		if 'response' in context:
			context.response.allow = {i.upper() for i in safe if ismethod(getattr(obj, i, None)) or i in {'head', 'options'}}

		if path and path[0] in safe:
			consumed = attr = path.popleft()
			attr = getattr(obj, attr, None)
			if not attr and attr in {'head', 'options'}:
				attr = partial(getattr(self, attr), obj)

			if isclass(attr):
				yield consumed, attr(context, obj, None), False
				return

			yield consumed, attr, True
			return

		if path and Resource:
			try:
				obj = Resource(context, obj, obj[path[0]])
			except KeyError:
				pass
			else:
				yield path.popleft(), obj, False

			return

		if verb and verb in safe:
			obj = getattr(obj, verb, None)
			if not obj and verb in {'head', 'options'}:
				obj = partial(getattr(self, verb), obj)
			yield None, obj, True
			return

		yield None, invalid_method, True

	def head(self, obj, *args, **kw):
		"""Allow the get method to set headers, but return no content.

		This performs an internal GET and strips the body from the response.
		"""
		obj.get(*args, **kw)
		return

	def options(self, obj, *args, **kw):
		"""The allowed methods are present in the returned headers."""
		return None

<commit_msg>Care not about testing rig coverage.<commit_after># encoding: utf-8

import warnings

if __debug__:
	from collections import deque

from functools import partial
from inspect import isclass, ismethod

from .exc import InvalidMethod

log = __import__('logging').getLogger(__name__)

def invalid_method(*args, **kw):
	raise InvalidMethod()

class ResourceDispatch(object):
	__slots__ = ()

	def __repr__(self):
		return "ResourceDispatch(0x{id})".format(id=id(self), self=self)

	def __call__(self, context, obj, path):
		verb = getattr(context, 'environ', context)['REQUEST_METHOD'].lower() if context else 'get'

		if __debug__:
			if not isinstance(path, deque):  # pragma: no cover
				warnings.warn(
						"Your code is not providing the path as a deque; this will be cast in development but"
						"will explode gloriously if run in a production environment.",
						RuntimeWarning, stacklevel=1
					)

				if isinstance(path, str):
					path = deque(path.split('/')[1 if not path or path.startswith('/') else 0:])
				else:
					path = deque(path)

			log.debug("Preparing resource dispatch. " + repr(obj), extra=dict(
					dispatcher = repr(self),
					context = repr(context),
					obj = repr(obj),
					path = list(path),
					verb = verb,
				))

		if isclass(obj):
			obj = obj(context, None, None)
			yield None, obj, False  # Announce class instantiation.

		consumed = None
		Resource = getattr(obj, '__resource__', None)
		safe = {i for i in dir(obj) if i[0] != '_'} | {'options'}
		if 'get' in safe: safe.add('head')

		if 'response' in context:
			context.response.allow = {i.upper() for i in safe if ismethod(getattr(obj, i, None)) or i in {'head', 'options'}}

		if path and path[0] in safe:
			consumed = attr = path.popleft()
			attr = getattr(obj, attr, None)
			if not attr and attr in {'head', 'options'}:
				attr = partial(getattr(self, attr), obj)

			if isclass(attr):
				yield consumed, attr(context, obj, None), False
				return

			yield consumed, attr, True
			return

		if path and Resource:
			try:
				obj = Resource(context, obj, obj[path[0]])
			except KeyError:
				pass
			else:
				yield path.popleft(), obj, False

			return

		if verb and verb in safe:
			obj = getattr(obj, verb, None)
			if not obj and verb in {'head', 'options'}:
				obj = partial(getattr(self, verb), obj)
			yield None, obj, True
			return

		yield None, invalid_method, True

	def head(self, obj, *args, **kw):
		"""Allow the get method to set headers, but return no content.

		This performs an internal GET and strips the body from the response.
		"""
		obj.get(*args, **kw)
		return

	def options(self, obj, *args, **kw):
		"""The allowed methods are present in the returned headers."""
		return None

<|endoftext|>


<commit_before># Copyright 2014 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import os
import re
import sys

import webapp2
from google.appengine.api import images
from google.appengine.api import urlfetch

sys.path.append(os.path.join(os.path.dirname(__file__),'../lib'))
from bs4 import BeautifulSoup
import cloudstorage as gcs

from handlers.common import *
from models import FeaturedArtwork

THUMB_HEIGHT=600
NO_CROP_TUPLE=(0, 0, 1, 1)

def add_art_from_external_details_url(publish_date, url):
  if FeaturedArtwork.all().filter('publish_date =', publish_date).get() != None:
    webapp2.abort(409, message='Artwork already exists for this date.')

  result = urlfetch.fetch(url)
  if result.status_code < 200 or result.status_code >= 300:
    webapp2.abort(400, message='Error processing URL: HTTP %d. Content: %s'
        % (result.status_code, result.content))

  soup = BeautifulSoup(result.content, 'html.parser')
  attribution = None

  if re.search(r'wikiart.org', url, re.I) or re.search(r'wikipaintings.org', url, re.I):
    attribution = 'wikiart.org'
    details_url = re.sub(r'#.+', '', url, re.I | re.S) + '?utm_source=Muzei&utm_campaign=Muzei'
    title = soup.find('h1').get_text()
    author = soup.find('a', class_='artist-name').get_text()
    completion_year = None
    try:
      completion_year = unicode(soup.find(text='Date:').parent.next_sibling).strip()
    except:
      pass
    byline = author + ((', ' + completion_year) if completion_year else '')
    image_url = get_wikiart_image_url(soup)
  elif re.search(r'metmuseum.org', url, re.I):
    attribution = 'metmuseum.org'
    details_url = re.sub(r'[#?].+', '', url, re.I | re.S) + '?utm_source=Muzei&utm_campaign=Muzei'
    title = soup.find('h2').get_text()
    author = ''
    try:
      author = unicode(soup.find(text='Artist:').parent.next_sibling).strip()
    except:
      pass
    author = re.sub(r'\s*\(.*', '', author)
    completion_year = None
    try:
      completion_year = unicode(soup.find(text='Date:').parent.next_sibling).strip()
    except:
      pass
    byline = author + ((', ' + completion_year) if completion_year else '')
    image_url = soup.find('a', class_='download').attrs['href']
  else:
    webapp2.abort(400, message='Unrecognized URL')

  if not title or not author or not image_url:
    webapp2.abort(500, message='Could not parse HTML')

  image_url, thumb_url = maybe_process_image(image_url,
      NO_CROP_TUPLE,
      publish_date.strftime('%Y%m%d') + ' ' + title + ' ' + byline)

  # create the artwork entry
  new_artwork = FeaturedArtwork(
      title=title.strip(),
      byline=byline.strip(),
      attribution=attribution,
      image_url=image_url,
      thumb_url=thumb_url,
      details_url=details_url,
      publish_date=publish_date)
  new_artwork.save()

  return new_artwork

def get_wikiart_image_url(soup):
  # TODO: use a cleaner method :(
  tmp = soup.find(class_='thumbnails_ref')['onclick']
  thumb_html_url = re.search(r'(/en.+?)\'', tmp).group(1)
  thumb_html_url = "http://www.wikiart.org%s" % thumb_html_url
  result = urlfetch.fetch(thumb_html_url)
  if result.status_code < 200 or result.status_code >= 300:
    webapp2.abort(400, message='Error processing URL: HTTP %d. Content: %s'
        % (result.status_code, result.content))

  thumb_html = json.loads(result.content)
  thumb_soup = BeautifulSoup(thumb_html, 'html.parser')
  max_thumb_width = 0
  max_thumb_url = None
  for thumb_title_el in thumb_soup.select('.thumbnail_title'):
    thumb_width = int(re.search(r'(\d+)x\d+', thumb_title_el.get_text()).group(1))
    if thumb_width > max_thumb_width:
      max_thumb_width = thumb_width
      max_thumb_url = thumb_title_el.parent.find('a')['href']

  return max_thumb_url

def maybe_process_image(image_url, crop_tuple, base_name):
  if CLOUD_STORAGE_ROOT_URL in image_url and crop_tuple == NO_CROP_TUPLE:
    return (image_url, None)

  image_result = urlfetch.fetch(image_url, deadline=20)
  if image_result.status_code < 200 or image_result.status_code >= 300:
    raise IOError('Error downloading image: HTTP %d.' % image_result.status_code)

  filename = re.sub(r'[^\w]+', '-', base_name.strip().lower()) + '.jpg'

  # main image
  image_gcs_path = CLOUD_STORAGE_BASE_PATH + '/fullres/' + filename
  # resize to max width 4000 or max height 2000
  image_contents = image_result.content
  image = images.Image(image_contents)
  edited = False
  if image.height > 2000:
    image.resize(width=(image.width * 2000 / image.height), height=2000)
    edited = True
  elif image.width > 4000:
    image.resize(width=4000, height=(image.height * 4000 / image.width))
    edited = True

  if crop_tuple != NO_CROP_TUPLE:
    image.crop(*crop_tuple)
    edited = True

  if edited:
    image_contents = image.execute_transforms(output_encoding=images.JPEG, quality=80)

  # upload with default ACLs set on the bucket  # or use options={'x-goog-acl': 'public-read'})
  gcs_file = gcs.open(image_gcs_path, 'w', content_type='image/jpeg')
  gcs_file.write(image_contents)
  gcs_file.close()

  # thumb
  thumb_gcs_path = CLOUD_STORAGE_BASE_PATH + '/thumbs/' + filename
  thumb = images.Image(image_result.content)
  thumb.resize(width=(thumb.width * THUMB_HEIGHT / thumb.height), height=THUMB_HEIGHT)

  if crop_tuple != NO_CROP_TUPLE:
    thumb.crop(*crop_tuple)
    edited = True

  thumb_contents = thumb.execute_transforms(output_encoding=images.JPEG, quality=40)
  gcs_file = gcs.open(thumb_gcs_path, 'w', content_type='image/jpeg')
  gcs_file.write(thumb_contents)
  gcs_file.close()

  return (CLOUD_STORAGE_ROOT_URL + image_gcs_path,
          CLOUD_STORAGE_ROOT_URL + thumb_gcs_path)

<commit_msg>web/featured art: fix wikiart completion year parsing<commit_after># Copyright 2014 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import os
import re
import sys

import webapp2
from google.appengine.api import images
from google.appengine.api import urlfetch

sys.path.append(os.path.join(os.path.dirname(__file__),'../lib'))
from bs4 import BeautifulSoup
import cloudstorage as gcs

from handlers.common import *
from models import FeaturedArtwork

THUMB_HEIGHT=600
NO_CROP_TUPLE=(0, 0, 1, 1)

def add_art_from_external_details_url(publish_date, url):
  if FeaturedArtwork.all().filter('publish_date =', publish_date).get() != None:
    webapp2.abort(409, message='Artwork already exists for this date.')

  result = urlfetch.fetch(url)
  if result.status_code < 200 or result.status_code >= 300:
    webapp2.abort(400, message='Error processing URL: HTTP %d. Content: %s'
        % (result.status_code, result.content))

  soup = BeautifulSoup(result.content, 'html.parser')
  attribution = None

  if re.search(r'wikiart.org', url, re.I) or re.search(r'wikipaintings.org', url, re.I):
    attribution = 'wikiart.org'
    details_url = re.sub(r'#.+', '', url, re.I | re.S) + '?utm_source=Muzei&utm_campaign=Muzei'
    title = soup.find('h1').get_text()
    author = soup.find('a', class_='artist-name').get_text()
    completion_year = None
    try:
      completion_year = unicode(soup
          .find(text='Date:')
          .parent
          .find_next_sibling('span')
          .text).strip()
    except:
      pass
    byline = author + ((', ' + completion_year) if completion_year else '')
    image_url = get_wikiart_image_url(soup)
  elif re.search(r'metmuseum.org', url, re.I):
    attribution = 'metmuseum.org'
    details_url = re.sub(r'[#?].+', '', url, re.I | re.S) + '?utm_source=Muzei&utm_campaign=Muzei'
    title = soup.find('h2').get_text()
    author = ''
    try:
      author = unicode(soup.find(text='Artist:').parent.next_sibling).strip()
    except:
      pass
    author = re.sub(r'\s*\(.*', '', author)
    completion_year = None
    try:
      completion_year = unicode(soup.find(text='Date:').parent.next_sibling).strip()
    except:
      pass
    byline = author + ((', ' + completion_year) if completion_year else '')
    image_url = soup.find('a', class_='download').attrs['href']
  else:
    webapp2.abort(400, message='Unrecognized URL')

  if not title or not author or not image_url:
    webapp2.abort(500, message='Could not parse HTML')

  image_url, thumb_url = maybe_process_image(image_url,
      NO_CROP_TUPLE,
      publish_date.strftime('%Y%m%d') + ' ' + title + ' ' + byline)

  # create the artwork entry
  new_artwork = FeaturedArtwork(
      title=title.strip(),
      byline=byline.strip(),
      attribution=attribution,
      image_url=image_url,
      thumb_url=thumb_url,
      details_url=details_url,
      publish_date=publish_date)
  new_artwork.save()

  return new_artwork

def get_wikiart_image_url(soup):
  # TODO: use a cleaner method :(
  tmp = soup.find(class_='thumbnails_ref')['onclick']
  thumb_html_url = re.search(r'(/en.+?)\'', tmp).group(1)
  thumb_html_url = "http://www.wikiart.org%s" % thumb_html_url
  result = urlfetch.fetch(thumb_html_url)
  if result.status_code < 200 or result.status_code >= 300:
    webapp2.abort(400, message='Error processing URL: HTTP %d. Content: %s'
        % (result.status_code, result.content))

  thumb_html = json.loads(result.content)
  thumb_soup = BeautifulSoup(thumb_html, 'html.parser')
  max_thumb_width = 0
  max_thumb_url = None
  for thumb_title_el in thumb_soup.select('.thumbnail_title'):
    thumb_width = int(re.search(r'(\d+)x\d+', thumb_title_el.get_text()).group(1))
    if thumb_width > max_thumb_width:
      max_thumb_width = thumb_width
      max_thumb_url = thumb_title_el.parent.find('a')['href']

  return max_thumb_url

def maybe_process_image(image_url, crop_tuple, base_name):
  if CLOUD_STORAGE_ROOT_URL in image_url and crop_tuple == NO_CROP_TUPLE:
    return (image_url, None)

  image_result = urlfetch.fetch(image_url, deadline=20)
  if image_result.status_code < 200 or image_result.status_code >= 300:
    raise IOError('Error downloading image: HTTP %d.' % image_result.status_code)

  filename = re.sub(r'[^\w]+', '-', base_name.strip().lower()) + '.jpg'

  # main image
  image_gcs_path = CLOUD_STORAGE_BASE_PATH + '/fullres/' + filename
  # resize to max width 4000 or max height 2000
  image_contents = image_result.content
  image = images.Image(image_contents)
  edited = False
  if image.height > 2000:
    image.resize(width=(image.width * 2000 / image.height), height=2000)
    edited = True
  elif image.width > 4000:
    image.resize(width=4000, height=(image.height * 4000 / image.width))
    edited = True

  if crop_tuple != NO_CROP_TUPLE:
    image.crop(*crop_tuple)
    edited = True

  if edited:
    image_contents = image.execute_transforms(output_encoding=images.JPEG, quality=80)

  # upload with default ACLs set on the bucket  # or use options={'x-goog-acl': 'public-read'})
  gcs_file = gcs.open(image_gcs_path, 'w', content_type='image/jpeg')
  gcs_file.write(image_contents)
  gcs_file.close()

  # thumb
  thumb_gcs_path = CLOUD_STORAGE_BASE_PATH + '/thumbs/' + filename
  thumb = images.Image(image_result.content)
  thumb.resize(width=(thumb.width * THUMB_HEIGHT / thumb.height), height=THUMB_HEIGHT)

  if crop_tuple != NO_CROP_TUPLE:
    thumb.crop(*crop_tuple)
    edited = True

  thumb_contents = thumb.execute_transforms(output_encoding=images.JPEG, quality=40)
  gcs_file = gcs.open(thumb_gcs_path, 'w', content_type='image/jpeg')
  gcs_file.write(thumb_contents)
  gcs_file.close()

  return (CLOUD_STORAGE_ROOT_URL + image_gcs_path,
          CLOUD_STORAGE_ROOT_URL + thumb_gcs_path)

<|endoftext|>


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

# Copyright 2015-2016 Odoo S.A.
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017-2018 Rémy Taymans <remytaymans@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from werkzeug.exceptions import Forbidden, NotFound

from openerp import http
from openerp.exceptions import AccessError, MissingError
from openerp.http import request

from openerp.addons.website_portal_v10.controllers.main import WebsiteAccount

class CooperatorWebsiteAccount(WebsiteAccount):

    @http.route()
    def account(self):
        """ Add Tax Shelter Certificate to main account page """
        response = super(CooperatorWebsiteAccount, self).account()
        partner = request.env.user.partner_id

        tax_shelter_mgr = request.env['tax.shelter.certificate'].sudo()
        tax_shelter_count = tax_shelter_mgr.search_count([
            ('partner_id', 'in', [partner.commercial_partner_id.id]),
        ])

        response.qcontext.update({
            'tax_shelter_count': tax_shelter_count,
        })
        return response

    @http.route(
        ['/my/tax_shelter_certificate',
         '/my/tax_shelter_certificate/page/<int:page>'],
        type='http', auth="user", website=True)
    def portal_my_tax_shelter_certificate(self, page=1, date_begin=None,
                                          date_end=None, **kw):
        """Render a page that lits the tax shelter report:
            * Subscriptions Certificates
            * Shares Certifcates
        """
        values = self._prepare_portal_layout_values()
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate'].sudo()

        domain = [
            ('partner_id', 'in', [partner.commercial_partner_id.id]),
        ]

        if date_begin and date_end:
            domain += [('create_date', '>=', date_begin),
                       ('create_date', '<', date_end)]

        # count for pager
        tax_shelter_count = tax_shelter_mgr.search_count(domain)
        # pager
        pager = request.website.pager(
            url="/my/tax_shelter_certificate",
            url_args={'date_begin': date_begin, 'date_end': date_end},
            total=tax_shelter_count,
            page=page,
            step=self._items_per_page
        )
        # content according to pager and archive selected
        tax_shelters = tax_shelter_mgr.search(
            domain, limit=self._items_per_page, offset=pager['offset'])
        tax_shelters = tax_shelters.sorted(
            key=lambda r: r.declaration_id.fiscal_year,
            reverse=True
        )
        values.update({
            'date': date_begin,
            'tax_shelters': tax_shelters,
            'page_name': 'invoice',
            'pager': pager,
            'default_url': '/my/tax_shelter_certificate',
        })
        return request.website.render(
            "easy_my_coop_website_taxshelter.portal_my_tax_shelter",
            values
        )

    @http.route(['/my/subscription_certificate/pdf/<int:oid>'],
                type='http', auth="user", website=True)
    def get_subscription_certificate_pdf(self, oid=-1):
        """Render the Subscription Certificate pdf of the given
        Tax Shelter Report
        """
        # Get the subscription certificate and raise an error if the user
        # is not allowed to access to it or if the object is not found.
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate'].sudo()
        tax_shelter = tax_shelter_mgr.browse(oid)
        try:
            if tax_shelter.partner_id != partner:
                raise Forbidden()
        except AccessError:
            raise Forbidden()
        except MissingError:
            raise NotFound()
        # Get the pdf
        report_mgr = request.env['report'].sudo()
        pdf = report_mgr.get_pdf(
            tax_shelter,
            'easy_my_coop_taxshelter_report.tax_shelter_subscription_report'
        )
        filename = "Subscription Certificate - %s - %s" % (
            partner.name,
            tax_shelter.declaration_id.fiscal_year
        )
        return self._render_pdf(pdf, filename)

    @http.route(['/my/share_certificate/pdf/<int:oid>'],
                type='http', auth="user", website=True)
    def get_share_certificate_pdf(self, oid=-1):
        """Render the Share Certificate pdf of the given Tax Shelter
        Report
        """
        # Get the share certificate and raise an error if the user
        # is not allowed to access to it or if the object is not found.
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate'].sudo()
        tax_shelter = tax_shelter_mgr.browse(oid)
        try:
            if tax_shelter.partner_id != partner:
                raise Forbidden()
        except AccessError:
            raise Forbidden()
        except MissingError:
            raise NotFound()
        # Get the pdf
        report_mgr = request.env['report'].sudo()
        pdf = report_mgr.get_pdf(
            tax_shelter,
            'easy_my_coop_taxshelter_report.tax_shelter_shares_report'
        )
        filename = "Share Certificate - %s - %s" % (
            partner.name,
            tax_shelter.declaration_id.fiscal_year
        )
        return self._render_pdf(pdf, filename)

    def _render_pdf(self, pdf, filename):
        """Render a http response for a pdf"""
        pdfhttpheaders = [
            ('Content-Disposition', 'inline; filename="%s.pdf"' % filename),
            ('Content-Type', 'application/pdf'),
            ('Content-Length', len(pdf))
        ]
        return request.make_response(pdf, headers=pdfhttpheaders)
<commit_msg>[FIX] emc_w_taxshelter: Use sudo explicitly<commit_after># -*- coding: utf-8 -*-

# Copyright 2015-2016 Odoo S.A.
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017-2018 Rémy Taymans <remytaymans@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from werkzeug.exceptions import Forbidden, NotFound

from openerp import http
from openerp.exceptions import AccessError, MissingError
from openerp.http import request

from openerp.addons.website_portal_v10.controllers.main import WebsiteAccount

class CooperatorWebsiteAccount(WebsiteAccount):

    @http.route()
    def account(self):
        """ Add Tax Shelter Certificate to main account page """
        response = super(CooperatorWebsiteAccount, self).account()
        partner = request.env.user.partner_id

        tax_shelter_mgr = request.env['tax.shelter.certificate']
        tax_shelter_count = tax_shelter_mgr.sudo().search_count([
            ('partner_id', 'in', [partner.commercial_partner_id.id]),
        ])

        response.qcontext.update({
            'tax_shelter_count': tax_shelter_count,
        })
        return response

    @http.route(
        ['/my/tax_shelter_certificate',
         '/my/tax_shelter_certificate/page/<int:page>'],
        type='http', auth="user", website=True)
    def portal_my_tax_shelter_certificate(self, page=1, date_begin=None,
                                          date_end=None, **kw):
        """Render a page that lits the tax shelter report:
            * Subscriptions Certificates
            * Shares Certifcates
        """
        values = self._prepare_portal_layout_values()
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate']

        domain = [
            ('partner_id', 'in', [partner.commercial_partner_id.id]),
        ]

        if date_begin and date_end:
            domain += [('create_date', '>=', date_begin),
                       ('create_date', '<', date_end)]

        # count for pager
        tax_shelter_count = tax_shelter_mgr.sudo().search_count(domain)
        # pager
        pager = request.website.pager(
            url="/my/tax_shelter_certificate",
            url_args={'date_begin': date_begin, 'date_end': date_end},
            total=tax_shelter_count,
            page=page,
            step=self._items_per_page
        )
        # content according to pager and archive selected
        tax_shelters = tax_shelter_mgr.sudo().search(
            domain, limit=self._items_per_page, offset=pager['offset'])
        tax_shelters = tax_shelters.sorted(
            key=lambda r: r.declaration_id.fiscal_year,
            reverse=True
        )
        values.update({
            'date': date_begin,
            'tax_shelters': tax_shelters,
            'page_name': 'invoice',
            'pager': pager,
            'default_url': '/my/tax_shelter_certificate',
        })
        return request.website.render(
            "easy_my_coop_website_taxshelter.portal_my_tax_shelter",
            values
        )

    @http.route(['/my/subscription_certificate/pdf/<int:oid>'],
                type='http', auth="user", website=True)
    def get_subscription_certificate_pdf(self, oid=-1):
        """Render the Subscription Certificate pdf of the given
        Tax Shelter Report
        """
        # Get the subscription certificate and raise an error if the user
        # is not allowed to access to it or if the object is not found.
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate']
        tax_shelter = tax_shelter_mgr.sudo().browse(oid)
        try:
            if tax_shelter.partner_id != partner:
                raise Forbidden()
        except AccessError:
            raise Forbidden()
        except MissingError:
            raise NotFound()
        # Get the pdf
        report_mgr = request.env['report'].sudo()
        pdf = report_mgr.get_pdf(
            tax_shelter,
            'easy_my_coop_taxshelter_report.tax_shelter_subscription_report'
        )
        filename = "Subscription Certificate - %s - %s" % (
            partner.name,
            tax_shelter.declaration_id.fiscal_year
        )
        return self._render_pdf(pdf, filename)

    @http.route(['/my/share_certificate/pdf/<int:oid>'],
                type='http', auth="user", website=True)
    def get_share_certificate_pdf(self, oid=-1):
        """Render the Share Certificate pdf of the given Tax Shelter
        Report
        """
        # Get the share certificate and raise an error if the user
        # is not allowed to access to it or if the object is not found.
        partner = request.env.user.partner_id
        tax_shelter_mgr = request.env['tax.shelter.certificate']
        tax_shelter = tax_shelter_mgr.sudo().browse(oid)
        try:
            if tax_shelter.partner_id != partner:
                raise Forbidden()
        except AccessError:
            raise Forbidden()
        except MissingError:
            raise NotFound()
        # Get the pdf
        report_mgr = request.env['report']
        pdf = report_mgr.sudo().get_pdf(
            tax_shelter,
            'easy_my_coop_taxshelter_report.tax_shelter_shares_report'
        )
        filename = "Share Certificate - %s - %s" % (
            partner.name,
            tax_shelter.declaration_id.fiscal_year
        )
        return self._render_pdf(pdf, filename)

    def _render_pdf(self, pdf, filename):
        """Render a http response for a pdf"""
        pdfhttpheaders = [
            ('Content-Disposition', 'inline; filename="%s.pdf"' % filename),
            ('Content-Type', 'application/pdf'),
            ('Content-Length', len(pdf))
        ]
        return request.make_response(pdf, headers=pdfhttpheaders)
<|endoftext|>


<commit_before>from framework import utils

def serialize_meta_schema(meta_schema):
    if not meta_schema:
        return None
    return {
        'id': meta_schema._id,
        'schema_name': meta_schema.name,
        'schema_version': meta_schema.schema_version,
        'schema': meta_schema.schema,
        'fulfills': meta_schema.fulfills,
        'requires_approval': meta_schema.requires_approval,
        'messages': meta_schema.messages
    }

def serialize_meta_schemas(meta_schemas):
    return [serialize_meta_schema(schema) for schema in (meta_schemas or [])]

def serialize_draft_registration(draft, auth=None):
    from website.profile.utils import serialize_user  # noqa
    from website.project.utils import serialize_node  # noqa

    node = draft.branched_from

    return {
        'pk': draft._id,
        'branched_from': serialize_node(draft.branched_from, auth),
        'initiator': serialize_user(draft.initiator, full=True),
        'registration_metadata': draft.registration_metadata,
        'registration_schema': serialize_meta_schema(draft.registration_schema[0]),
        'initiated': utils.iso8601format(draft.datetime_initiated),
        'updated': utils.iso8601format(draft.datetime_updated),
        'flags': draft.flags,
        'urls': {
            'edit': node.web_url_for('edit_draft_registration_page', draft_id=draft._id),
            'before_register': node.api_url_for('project_before_register'),
            'register': node.api_url_for('register_draft_registration', draft_id=draft._id),
            'register_page': node.web_url_for('draft_before_register_page', draft_id=draft._id),
            'registrations': node.web_url_for('node_registrations')
        },
        'requires_approval': draft.requires_approval,
        'is_pending_approval': draft.is_pending_review,
        'is_approved': draft.is_approved,
    }
<commit_msg>Draft reg has only one schema<commit_after>from framework import utils

def serialize_meta_schema(meta_schema):
    if not meta_schema:
        return None
    return {
        'id': meta_schema._id,
        'schema_name': meta_schema.name,
        'schema_version': meta_schema.schema_version,
        'schema': meta_schema.schema,
        'fulfills': meta_schema.fulfills,
        'requires_approval': meta_schema.requires_approval,
        'messages': meta_schema.messages
    }

def serialize_meta_schemas(meta_schemas):
    return [serialize_meta_schema(schema) for schema in (meta_schemas or [])]

def serialize_draft_registration(draft, auth=None):
    from website.profile.utils import serialize_user  # noqa
    from website.project.utils import serialize_node  # noqa

    node = draft.branched_from

    return {
        'pk': draft._id,
        'branched_from': serialize_node(draft.branched_from, auth),
        'initiator': serialize_user(draft.initiator, full=True),
        'registration_metadata': draft.registration_metadata,
        'registration_schema': serialize_meta_schema(draft.registration_schema),
        'initiated': utils.iso8601format(draft.datetime_initiated),
        'updated': utils.iso8601format(draft.datetime_updated),
        'flags': draft.flags,
        'urls': {
            'edit': node.web_url_for('edit_draft_registration_page', draft_id=draft._id),
            'before_register': node.api_url_for('project_before_register'),
            'register': node.api_url_for('register_draft_registration', draft_id=draft._id),
            'register_page': node.web_url_for('draft_before_register_page', draft_id=draft._id),
            'registrations': node.web_url_for('node_registrations')
        },
        'requires_approval': draft.requires_approval,
        'is_pending_approval': draft.is_pending_review,
        'is_approved': draft.is_approved,
    }
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Python source code encoding : https://www.python.org/dev/peps/pep-0263/
##############################################################################
#
#    OpenERP, Odoo Source Management Solution
#    Copyright (c) 2015 Antiun Ingeniería S.L. (http://www.antiun.com)
#                       Antonio Espinosa <antonioea@antiun.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/>.
#
##############################################################################
{
    'name': "Website legal page",
    'category': 'Website',
    'version': '1.0',
    'depends': [
        'website',
    ],
    'data': [
        'views/website_legal.xml',
        'views/website_privacy.xml',
        'views/website_terms.xml',
    ],
    'author': 'Antiun Ingeniería S.L., '
              'Odoo Community Association (OCA)',
    'website': 'http://www.antiun.com',
    'license': 'AGPL-3',
    'demo': [],
    'test': [],
    'installable': True,
}
<commit_msg>[UPD] prefix versions with 8.0<commit_after># -*- coding: utf-8 -*-
# Python source code encoding : https://www.python.org/dev/peps/pep-0263/
##############################################################################
#
#    OpenERP, Odoo Source Management Solution
#    Copyright (c) 2015 Antiun Ingeniería S.L. (http://www.antiun.com)
#                       Antonio Espinosa <antonioea@antiun.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/>.
#
##############################################################################
{
    'name': "Website legal page",
    'category': 'Website',
    'version': '8.0.1.0.0',
    'depends': [
        'website',
    ],
    'data': [
        'views/website_legal.xml',
        'views/website_privacy.xml',
        'views/website_terms.xml',
    ],
    'author': 'Antiun Ingeniería S.L., '
              'Odoo Community Association (OCA)',
    'website': 'http://www.antiun.com',
    'license': 'AGPL-3',
    'demo': [],
    'test': [],
    'installable': True,
}
<|endoftext|>


<commit_before>import shutil
import subprocess
import sys
import csv
import fileinput
import re

import constants

def train(output_graphs, data=None, weight_file=None, note=None):
    print("Training data, generating graphs: %r" % output_graphs)

    run_trainer()
    generate_parsed_logs()
    (training_details, validation_details) = parse_logs()

def run_trainer():
    """
    Runs Caffe to train the model.
    """
    print("\tRunning trainer...")
    with open(constants.OUTPUT_LOG_PATH, "w") as f:
        process = subprocess.Popen([constants.CAFFE_HOME + "/build/tools/caffe", "train",
            "--solver=" + constants.SOLVER_FILE],
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        for line in iter(process.stdout.readline, ''):
            sys.stdout.write(line)
            f.write(line)

        print("\t\tTraining output saved to %s" % constants.OUTPUT_LOG_PATH)

def generate_parsed_logs():
    """
    Takes the raw Caffe output created while training the model in order
    to generate reduced statistics, such as giving iterations vs. test loss.
    """

    print("\tParsing logs...")
    process = subprocess.Popen([constants.CAFFE_HOME + "/tools/extra/parse_log.py",
        constants.OUTPUT_LOG_PATH, constants.LOG_DIR], stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    for line in iter(process.stdout.readline, ''):
        sys.stdout.write(line)

    shutil.rmtree(constants.OUTPUT_LOG_PATH + ".validate", ignore_errors=True)
    shutil.move(constants.OUTPUT_LOG_PATH + ".test",
        constants.OUTPUT_LOG_PATH + ".validate")

    # Convert the commas in the files into tabs to make them easier to read.
    log_files = [constants.OUTPUT_LOG_PATH + ".train",
        constants.OUTPUT_LOG_PATH + ".validate"]
    for line in fileinput.input(log_files, inplace=True):
        line = line.replace(u",", u"\t")
        if fileinput.isfirstline():
            # HACK(neuberg): The column headers with tabs don't quite line up, so shorten
            # some column names and add a tab.
            line = line.replace(u"NumIters", u"Iters")
            line = line.replace(u"LearningRate", u"\tLR")

        sys.stdout.write(line)
    fileinput.close()

    logs = [
        {"title": "Testing", "filename": "train"},
        {"title": "Validation", "filename": "validate"}
    ]
    for log in logs:
        print("\n\t\tParsed %s log:" % log["title"])
        with open(constants.OUTPUT_LOG_PATH + "." + log["filename"], "r") as f:
            lines = f.read().split("\n")
            for line in lines:
                print("\t\t\t%s" % line)

    print("\t\tParsed training log saved to %s" % (constants.OUTPUT_LOG_PATH + ".train"))
    print("\t\tParsed validation log saved to %s\n" % (constants.OUTPUT_LOG_PATH + ".validate"))

def parse_logs():
    """
    Parses our training and validation logs in order to return them in a way we can work with.
    """
    training_iters = []
    training_loss = []
    for line in csv.reader(open(constants.OUTPUT_LOG_PATH + ".train"), delimiter="\t",
                            skipinitialspace=True):
        if re.search("Iters", str(line)):
            continue

        training_iters.append(int(float(line[0])))
        training_loss.append(float(line[3]))

    validation_iters = []
    validation_loss = []
    for line in csv.reader(open(constants.OUTPUT_LOG_PATH + ".validate"), delimiter="\t",
                            skipinitialspace=True):
        if re.search("Iters", str(line)):
            continue

        validation_iters.append(int(float(line[0])))
        validation_loss.append(float(line[3]))

    return (
        {
            "iters": training_iters,
            "loss": training_loss
        }, {
            "iters": validation_iters,
            "loss": validation_loss
        }
    )
<commit_msg>Get the weight file we just trained.<commit_after>import shutil
import subprocess
import sys
import csv
import fileinput
import re

import constants

def train(output_graphs, data=None, weight_file=None, note=None):
    print("Training data, generating graphs: %r" % output_graphs)

    run_trainer()
    generate_parsed_logs()
    (training_details, validation_details) = parse_logs()
    # TODO(neuberg): This will need to be adapted against an already trained weight
    # file that we are fine-tuning.
    trained_weight_file = get_trained_weight_file()

    # if output_graphs:
    #     graph.plot_results(training_details, validation_details, note)

    #     # If no weight file is provided by callers to this method, parse out the one we just
    #     # trained.
    #     if weight_file == None:
    #         weight_file = trained_weight_file
    #     predict.test_validation(data, weight_file)

def run_trainer():
    """
    Runs Caffe to train the model.
    """
    print("\tRunning trainer...")
    # TODO(neuberg): This will need to be adapted against an already trained weight
    # file that we are fine-tuning.
    with open(constants.OUTPUT_LOG_PATH, "w") as f:
        process = subprocess.Popen([constants.CAFFE_HOME + "/build/tools/caffe", "train",
            "--solver=" + constants.SOLVER_FILE],
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        for line in iter(process.stdout.readline, ''):
            sys.stdout.write(line)
            f.write(line)

        print("\t\tTraining output saved to %s" % constants.OUTPUT_LOG_PATH)

def generate_parsed_logs():
    """
    Takes the raw Caffe output created while training the model in order
    to generate reduced statistics, such as giving iterations vs. test loss.
    """

    print("\tParsing logs...")
    process = subprocess.Popen([constants.CAFFE_HOME + "/tools/extra/parse_log.py",
        constants.OUTPUT_LOG_PATH, constants.LOG_DIR], stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    for line in iter(process.stdout.readline, ''):
        sys.stdout.write(line)

    shutil.rmtree(constants.OUTPUT_LOG_PATH + ".validate", ignore_errors=True)
    shutil.move(constants.OUTPUT_LOG_PATH + ".test",
        constants.OUTPUT_LOG_PATH + ".validate")

    # Convert the commas in the files into tabs to make them easier to read.
    log_files = [constants.OUTPUT_LOG_PATH + ".train",
        constants.OUTPUT_LOG_PATH + ".validate"]
    for line in fileinput.input(log_files, inplace=True):
        line = line.replace(u",", u"\t")
        if fileinput.isfirstline():
            # HACK(neuberg): The column headers with tabs don't quite line up, so shorten
            # some column names and add a tab.
            line = line.replace(u"NumIters", u"Iters")
            line = line.replace(u"LearningRate", u"\tLR")

        sys.stdout.write(line)
    fileinput.close()

    logs = [
        {"title": "Testing", "filename": "train"},
        {"title": "Validation", "filename": "validate"}
    ]
    for log in logs:
        print("\n\t\tParsed %s log:" % log["title"])
        with open(constants.OUTPUT_LOG_PATH + "." + log["filename"], "r") as f:
            lines = f.read().split("\n")
            for line in lines:
                print("\t\t\t%s" % line)

    print("\t\tParsed training log saved to %s" % (constants.OUTPUT_LOG_PATH + ".train"))
    print("\t\tParsed validation log saved to %s\n" % (constants.OUTPUT_LOG_PATH + ".validate"))

def parse_logs():
    """
    Parses our training and validation logs in order to return them in a way we can work with.
    """
    training_iters = []
    training_loss = []
    for line in csv.reader(open(constants.OUTPUT_LOG_PATH + ".train"), delimiter="\t",
                            skipinitialspace=True):
        if re.search("Iters", str(line)):
            continue

        training_iters.append(int(float(line[0])))
        training_loss.append(float(line[3]))

    validation_iters = []
    validation_loss = []
    for line in csv.reader(open(constants.OUTPUT_LOG_PATH + ".validate"), delimiter="\t",
                            skipinitialspace=True):
        if re.search("Iters", str(line)):
            continue

        validation_iters.append(int(float(line[0])))
        validation_loss.append(float(line[3]))

    return (
        {
            "iters": training_iters,
            "loss": training_loss
        }, {
            "iters": validation_iters,
            "loss": validation_loss
        }
    )

def get_trained_weight_file():
    """
    Parses out the file name of the model weight file we just trained.
    """
    trained_weight_file = None
    with open(constants.OUTPUT_LOG_PATH) as f:
        content = f.read()
        trained_weight_file = re.findall("Snapshotting to (.*)$", content, re.MULTILINE)[0]

    return trained_weight_file
<|endoftext|>


<commit_before>import csv
import re
import os
import numpy as np
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import word_tokenize
from sklearn import feature_extraction

class FeatureData():
    def __init__(self, article_file_path, stances_file_path):
        self.number_of_classes = 4
        self.classes = ["Agrees", "Disagrees", "Discusses", "Unrelated"]
        self.articles = self._get_articles(article_file_path) # list of dictionaries
        self.stances = self._get_stances(stances_file_path)
        self.number_of_stances = len(self.stances)
        self.number_of_articles = len(self.articles)

    def _get_articles(self, path):
        # Body ID, articleBody
        articles = []
        with open(path, 'r') as csv_file:
            reader = csv.DictReader(csv_file)
            for row in reader:
                articles.append(row)
        return articles

    def _get_stances(self, path):
        # Headline, Body ID, Stance
        stances = []
        with open(path, 'r') as csv_file:
            reader = csv.DictReader(csv_file)
            for row in reader:
                stances.append(row)
        return stances

def normalize_word(w):
    wordnet_lemmatizer = WordNetLemmatizer()
    return wordnet_lemmatizer(w).lower()

def clean(str):
    return " ".join(re.findall(r'w+', string, flags=re.UNICODE).lower())

def get_tokenized_lemmas(str):
    return [normalize_word(token) for token in word_tokenize(str)]

def remove_stopwords(list_of_tokens):
    return [word for word in list_of_tokens if word not in feature_extraction.text.ENGLISH_STOP_WORDS]

if __name__ == '__main__':
    fd = FeatureData('./train_bodies.csv', './train_stances.csv')

<commit_msg>Add method to retrieve fully cleaned article text.<commit_after>import csv
import re

from nltk.stem import WordNetLemmatizer
from nltk.tokenize import word_tokenize
from sklearn import feature_extraction

class FeatureData(object):
    def __init__(self, article_file_path, stances_file_path):
        self.number_of_classes = 4
        self.classes = ["Agrees", "Disagrees", "Discusses", "Unrelated"]
        self.articles = self._get_articles(article_file_path)  # list of dictionaries
        self.stances = self._get_stances(stances_file_path)
        self.number_of_stances = len(self.stances)
        self.number_of_articles = len(self.articles)

    def get_clean_articles(self):
        """Retrieves a list of dictionaries containing the fully cleaned articleBody and the Body ID of each article."""
        clean_articles = []

        for item in self.articles:
            cleaned_article = clean(item['articleBody'])
            tokens = tokenize_text(cleaned_article)
            no_stop_word_tokens = remove_stopwords(tokens)
            lemmatized_tokens = get_tokenized_lemmas(no_stop_word_tokens)
            clean_articles.append(' '.join(lemmatized_tokens))

        return clean_articles

    def get_clean_stances(self):
        """Retrieves a list of dictionaries containing the fully cleaned Headlines and the Body ID and Stance for
        each headline."""

        pass

    def _get_articles(self, path):
        # Body ID, articleBody
        articles = []
        with open(path, 'r') as csv_file:
            reader = csv.DictReader(csv_file)
            for row in reader:
                articles.append(row)
        return articles

    def _get_stances(self, path):
        # Headline, Body ID, Stance
        stances = []
        with open(path, 'r') as csv_file:
            reader = csv.DictReader(csv_file)
            for row in reader:
                stances.append(row)
        return stances

def normalize_word(w):
    lemmatizer = WordNetLemmatizer()
    return lemmatizer.lemmatize(w).lower()

def clean(text):
    return " ".join(re.findall(r'\w+', text.decode('utf-8'), flags=re.UNICODE)).lower()

def tokenize_text(text):
    return [token for token in word_tokenize(text)]

def remove_stopwords(list_of_tokens):
    return [word for word in list_of_tokens if word not in feature_extraction.text.ENGLISH_STOP_WORDS]

def get_tokenized_lemmas(tokens):
    return [normalize_word(token) for token in tokens]

if __name__ == '__main__':
    fd = FeatureData('data/train_bodies.csv', 'data/train_stances.csv')
    clean_articles = fd.get_clean_articles()
    print clean_articles[0]
<|endoftext|>