<commit_before>import os
import sys
import json
import skaffolding

generators = {
    'django': skaffolding.DjangoGenerator,
    'flask': skaffolding.FlaskGenerator,
}

def from_scratch_django(fixture_data):
    """Does all work required to setup a completely new application."""
    project_name = fixture_data['config']['project_root']
    app_name = fixture_data['config']['app_name']

    # TODO: this is kind of weird

    print('Deleting existing django project (if applicable)...')
    os.system('rm -r ' + project_name)

    print('Adding new django project...')
    os.system('django-admin.py startproject ' + project_name)

    print('Generating new django app...')
    new_app_django(fixture_data)

    print('Generating DB tables...')
    os.system('cd ' + project_name + ' && python manage.py syncdb --noinput')

    print('Generating DB test data...')
    os.system('python manage.py generate_fixtures')

    print('Jumping back down...')
    os.system('cd ..')

    # TODO: Automatically fix the below issues for user.
    # TODO: test with making a bunch of apps, in config

    print("""
    Okay! Everything is done.
    You just need to update a few things...

    1. Update your main urls file to capture the app underneath it
        e.g.
        urlpatterns += patterns('',
            (r'^', include('{}.{}.urls')),
        )

    2. Add the app to your settings.py INSTALLED_APPS
    3. Add any dependencies to your settings.py INSTALLED_APPS
        Bootstrap3, and FactoryBoy are both currently necessary dependencies
        That you'll need to install (e.g. `sudo pip install X`)

    See the README for more details.

    """.format(project_name, app_name))

def new_app_django(fixture_data):
    """A quick util to access the generator from command line"""
    print('Generating... app "{}" in project "{}"'.format(
        fixture_data['config']['app_name'],
        fixture_data['config']['project_root']))
    # TODO: add types for classes (with --type option, or config property),
    # instead of defaulting to django
    gen = generators['django'](fixture_data)
    gen.generate_all()

# Run when file is run
try:
    if not sys.argv[2]:
        print('No JSON arguments supplied.')
    if sys.argv[1] == '--json' and sys.argv[2].endswith('json'):
        json_file = sys.argv[2]
        with open(json_file, 'r') as json_data:
            fixture_data = dict(json.loads(json_data.read()))
            if fixture_data['config']['project_root']:
                from_scratch_django(fixture_data)
            else:
                new_app_django(fixture_data)
    else:
        print('`{}` is not a valid .json file'.format(sys.argv[2]))
except IndexError:
    print(('No arguments were specified.'
           ' Please provided a JSON file with'
           ' the `--json filename` parameter.'))
<commit_msg>Major refactor of CLI: - Fix bugs when using CD - Remove unreachable commands - Remove some text - Add notes for models/generation<commit_after>import os
import sys
import json
import skaffolding

generators = {
    'django': skaffolding.DjangoGenerator,
    'flask': skaffolding.FlaskGenerator,
}

def _clean(root_dir):
    print('Deleting existing project (if applicable) located at {}'.format(
        root_dir))
    os.system('rm -r ' + root_dir)

def from_scratch_django(fixture_data):
    """Does all work required to setup a completely new application."""
    project_name = fixture_data['config']['project_root']
    app_name = fixture_data['config']['app_name']
    root_dir = os.getcwd() + '/' + project_name + '/'
    settings_file = root_dir + '/' + project_name + '/settings.py'

    _clean(root_dir)

    print('Adding new django project...')
    os.system('django-admin.py startproject ' + project_name)

    print('Skaffolding app structure...')
    new_app_django(fixture_data)

    print("""
    Okay! Everything is done.
    You just need to update a few things...

    1. Update your main urls file to capture the app underneath it
        e.g.
        urlpatterns += patterns('',
            (r'^', include('{}.{}.urls')),
        )
        - or -
        Update the `ROOT_URLCONF` option in the django settings file
        to reference your specific app.

    2. Add the app to your settings.py INSTALLED_APPS
    3. Add any dependencies to your settings.py INSTALLED_APPS
        Bootstrap3, and FactoryBoy are both currently necessary dependencies
        That you'll need to install (e.g. `sudo pip install X`)
    4. Sync/migrate your models and install the fixture data!
        This is located in {settings}.
        The following command will get you going:
            `python manage.py syncdb --noinput &&
             python manage.py generate_fixtures`

    See the README for more details.

    """.format(project_name, app_name, settings=settings_file))

def new_app_django(fixture_data):
    """A quick util to access the generator from command line"""
    print('Generating app "{}" in project "{}"'.format(
        fixture_data['config']['app_name'],
        fixture_data['config']['project_root']))
    # TODO: add types for classes (with --type option, or config property),
    # instead of defaulting to django
    gen = generators['django'](fixture_data)
    gen.generate_all()

# Run when file is run
try:
    if not sys.argv[2]:
        print('No JSON arguments supplied.')
    if sys.argv[1] == '--json' and sys.argv[2].endswith('json'):
        json_file = sys.argv[2]
        with open(json_file, 'r') as json_data:
            fixture_data = dict(json.loads(json_data.read()))
            if fixture_data['config']['project_root']:
                from_scratch_django(fixture_data)
            else:
                new_app_django(fixture_data)
    else:
        print('`{}` is not a valid .json file'.format(sys.argv[2]))
except IndexError:
    print(('No arguments were specified.'
           ' Please provided a JSON file with'
           ' the `--json filename` parameter.'))
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import os, sys, re
import random
from time import time

import cv2
import numpy as np

import chainer
from chainer import cuda
import chainer.functions as F
from chainer.functions import caffe

parser = argparse.ArgumentParser(
    description='detect duplicate pictures')
parser.add_argument('image',  help='Path to a folder that contains image file')
parser.add_argument('--gpu',  default=-1, help='The argument is number of gpu. -1 means cpu')
args = parser.parse_args()

#use alexnet
print('alexnet is being loaded!')
timeMemory = time()
func = caffe.CaffeFunction("bvlc_alexnet.caffemodel")
print('alexnet was loaded!')
print('It took ' + str(int(time() - timeMemory)) + " secondes")
if args.gpu >= 0:
  cuda.init(args.gpu)
  func.to_gpu()

#input size
in_size = 227
mean_image = np.load("ilsvrc_2012_mean.npy")

# return neural code
def neuralCode(x):
  y, = func(inputs={'data': x}, outputs=['fc7'], train=False)
  return y.data[0]

cropwidth = 256 - in_size
start = cropwidth // 2
stop = start + in_size
mean_image = mean_image[:, start:stop, start:stop].copy()
target_shape = (256, 256)
output_side_length=256

#search pictures
picturePath = [picture for picture in os.listdir(args.image)
               if re.findall(r"\.png$|\.jpg$|\.JPG$|\.PNG$|\.JPEG$",picture)]
print("you have totally " + str(len(picturePath)) + " pictures in " + args.image)
answer = {}
count = 1

for picture in picturePath:
  timeMemory = time()
  print('Number of pictures: ' + str(count))
  count = count + 1
  print('extracting neural code of ' + args.image + "/" + picture)
  #load image file
  image = cv2.imread(args.image + "/" + picture)
  #resize and crop
  height, width, depth = image.shape
  new_height = output_side_length
  new_width = output_side_length
  if height > width:
      new_height = output_side_length * height / width
  else:
      new_width = output_side_length * width / height
  resized_img = cv2.resize(image, (new_width, new_height))
  height_offset = (new_height - output_side_length) / 2
  width_offset = (new_width - output_side_length) / 2
  image= resized_img[height_offset:height_offset + output_side_length,
                     width_offset:width_offset + output_side_length]

  #subtract mean image
  image = image.transpose(2, 0, 1)
  image = image[:, start:stop, start:stop].astype(np.float32)
  image -= mean_image

  x_batch = np.ndarray(
      (1, 3, in_size,in_size), dtype=np.float32)
  x_batch[0]=image

  if args.gpu >= 0:
      x_batch=cuda.to_gpu(x_batch)

  #get neural code
  x = chainer.Variable(x_batch, volatile=True)
  answer[picture] = neuralCode(x)
  print('It took ' + str(int(time() - timeMemory)) + " secondes")
<commit_msg>implement function to calculate precision and recall<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import os, sys, re
import random
from time import time

import cv2
import numpy as np

import chainer
from chainer import cuda
import chainer.functions as F
from chainer.functions import caffe

parser = argparse.ArgumentParser(
    description='detect duplicate pictures')
parser.add_argument('image', nargs="*",  help='Path to a folder that contains image file')
parser.add_argument('--gpu',  default=-1, help='The argument is number of gpu. -1 means cpu')
args = parser.parse_args()

print(args.image)
#use alexnet
print('alexnet is being loaded!')
timeMemory = time()
func = caffe.CaffeFunction("bvlc_alexnet.caffemodel")
print('alexnet was loaded!')
print('It took ' + str(int(time() - timeMemory)) + " secondes")
if args.gpu >= 0:
  cuda.init(args.gpu)
  func.to_gpu()

#input size
in_size = 227
mean_image = np.load("ilsvrc_2012_mean.npy")

# return neural code
def neuralCode(x):
  y, = func(inputs={'data': x}, outputs=['fc7'], train=False)
  return y.data[0]

# calculate precision, recall, F
def calcResult(answer, threshold):
  tp = 0
  fp = 0
  tn = 0
  fn = 0
  item = {}
  item["fpFile"] = []
  item["tnFile"] = []
  #precision = tp / (tp + fp)
  #recall = tp / (tp + fn)
  for key in answer:
    duplicate = []
    for keykey in answer:
      if key == keykey:
        pass
      else:
        distance = answer[key].dot(answer[keykey])/(np.linalg.norm(answer[key])*np.linalg.nor(answer[keykey]))
        if distance >= threshold and key.split('/')[-1] == keykey.split('/')[-1]:
          tp = tp + 1
        elif distance >= threshold and key.split('/')[-1] != keykey.split('/')[-1]:
          tn = tn + 1
          item["tnFile"].append = {key: keykey}
        elif distance <= threshold and key.split('/')[-1] != keykey.split('/')[-1]:
          fn = fn + 1
        elif distance <= threshold and key.split('/')[-1] == keykey.split('/')[-1]:
          fp = fp + 1
          item["fpFile"].append = {key: keykey}
    item["tp"] = tp
    item["fp"] = tp
    item["tn"] = tp
    item["fn"] = tp
    item["recall"] = tp / (tp + fn)
    item["precision"] = tp / (tp + fp)
    return item

cropwidth = 256 - in_size
start = cropwidth // 2
stop = start + in_size
mean_image = mean_image[:, start:stop, start:stop].copy()
target_shape = (256, 256)
output_side_length=256

for folderPath in args.image:
  #search pictures
  picturePath = [picture for picture in os.listdir(folderPath)
                 if re.findall(r"\.png$|\.jpg$|\.JPG$|\.PNG$|\.JPEG$",picture)]
  print("you have totally " + str(len(picturePath)) + " pictures in " + folderPath)
  answer = {}
  count = 1

  for picture in picturePath:
    timeMemory = time()
    print('Number of pictures: ' + str(count))
    count = count + 1
    print('extracting neural code of ' + folderPath + "/" + picture)
    #load image file
    image = cv2.imread(folderPath + "/" + picture)
    #resize and crop
    height, width, depth = image.shape
    new_height = output_side_length
    new_width = output_side_length
    if height > width:
        new_height = output_side_length * height / width
    else:
        new_width = output_side_length * width / height
    resized_img = cv2.resize(image, (new_width, new_height))
    height_offset = (new_height - output_side_length) / 2
    width_offset = (new_width - output_side_length) / 2
    image= resized_img[height_offset:height_offset + output_side_length,
                       width_offset:width_offset + output_side_length]

    #subtract mean image
    image = image.transpose(2, 0, 1)
    image = image[:, start:stop, start:stop].astype(np.float32)
    image -= mean_image

    x_batch = np.ndarray(
        (1, 3, in_size,in_size), dtype=np.float32)
    x_batch[0]=image

    if args.gpu >= 0:
        x_batch=cuda.to_gpu(x_batch)

    #get neural code
    x = chainer.Variable(x_batch, volatile=True)
    answer[folderPath + "/" +  picture] = neuralCode(x)
    print('It took ' + str(int(10*(time() - timeMemory))/10.0) + " secondes")

result = calcResult(answer)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DKB Credit card transaction QIF exporter
# Copyright (C) 2013 Christian Hoffmann <mail@hoffmann-christian.info>
#
# Inspired by Jens Herrmann <jens.herrmann@qoli.de>,
# but written using modern tools (argparse, csv reader, mechanize,
# BeautifulSoup)
#
# 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/>.

import re
import csv
import sys
import logging
from bs4 import BeautifulSoup
from mechanize import Browser

DEBUG = False

logger = logging.getLogger(__name__)

class DkbScraper(object):
    BASEURL = "https://banking.dkb.de/dkb/-"

    def __init__(self):
        self.br = Browser()

    def login(self, userid, pin):
        """
        Create a new session by submitting the login form

        @param str userid
        @param str pin
        """
        logger.info("Starting login as user %s...", userid)
        br = self.br

        # we are not a spider, so let's ignore robots.txt...
        br.set_handle_robots(False)

        # Although we have to handle a meta refresh, we disable it here
        # since mechanize seems to be buggy and will be stuck in a
        # long (infinite?) sleep() call
        br.set_handle_refresh(False)

        br.open(self.BASEURL + '?$javascript=disabled')

        # select login form:
        br.form = list(br.forms())[0]

        br.set_all_readonly(False)
        br.form["j_username"] = userid
        br.form["j_password"] = pin
        br.form["browserName"] = "Firefox"
        br.form["browserVersion"] = "40"
        br.form["screenWidth"] = "1000"
        br.form["screenHeight"] = "800"
        br.form["osName"] = "Windows"
        br.submit()
        br.open(self.BASEURL + "?$javascript=disabled")

    def credit_card_transactions_overview(self):
        """
        Navigates the internal browser state to the credit card
        transaction overview menu
        """
        logger.info("Navigating to 'Kreditkartenumsätze'...")
        br = self.br
        overview_html = BeautifulSoup(br.response().read())
        for link in br.links():
            if re.search("Kreditkartenums.*tze", link.text, re.I):
                br.follow_link(link)
                return
            if 'weitergeleitet' in link.text:
                br.follow_link(link)
            if link.text == 'here':
                br.follow_link(text="here")
        raise RuntimeError("Unable to find link 'Kreditkartenumsätze' -- "
            "Maybe the login went wrong?")

    def _get_transaction_selection_form(self):
        """
        Internal.

        Returns the transaction selection form object (mechanize)
        """
        for form in self.br.forms():
            try:
                form.find_control(name="slCreditCard")
                return form
            except Exception:
                continue

        raise RuntimeError("Unable to find transaction selection form")

    def _select_all_transactions_from(self, form, from_date, to_date):
        """
        Internal.

        Checks the radio box "Alle Umsätze vom" and populates the
        "from" and "to" with the given values.

        @param mechanize.HTMLForm form
        @param str from_date dd.mm.YYYY
        @param str to_date dd.mm.YYYY
        """
        try:
            radio_ctrl = form.find_control("searchPeriod")
        except Exception:
            raise RuntimeError("Unable to find search period radio box")

        all_transactions_item = None
        for item in radio_ctrl.items:
            for label in item.get_labels():
                if re.search('Alle Ums.*tze.*', label.text, re.I):
                    all_transactions_item = item
                    break

        if not all_transactions_item:
            raise RuntimeError(
                "Unable to find 'Alle Umsätze vom' radio box")

        form[radio_ctrl.name] = [all_transactions_item.name]

        try:
            from_item = form.find_control(name="postingDate")
        except Exception:
            raise RuntimeError("Unable to find 'ab' date field")

        from_item.value = from_date

        try:
            to_item = form.find_control(name="toPostingDate")
        except Exception:
            raise RuntimeError("Unable to find 'to' date field")

        to_item.value = to_date

    def _select_credit_card(self, form, cardid):
        """
        Internal.

        Selects the correct credit card from the dropdown menu in the
        transaction selection form.

        @param mechanize.HTMLForm form
        @param str cardid: last 4 digits of the relevant card number
        """
        try:
            cc_list = form.find_control(name="slCreditCard")
        except Exception:
            raise RuntimeError("Unable to find credit card selection form")

        for item in cc_list.get_items():
            # find right credit card...
            for label in item.get_labels():
                pattern = r'\b\S{12}(?<=%s)\b' % re.escape(cardid)
                if re.search(pattern, label.text, re.I):
                    form[cc_list.name] = [item.name]
                    return

        raise RuntimeError("Unable to find the right credit card")

    def select_transactions(self, cardid, from_date, to_date):
        """
        Changes the current view to show all transactions between
        from_date and to_date for the credit card identified by the
        given card id.

        @param str cardid: last 4 digits of your credit card's number
        @param str from_date dd.mm.YYYY
        @param str to_date dd.mm.YYYY
        """
        br = self.br
        logger.info("Selecting transactions in time frame %s - %s...",
            from_date, to_date)

        br.form = form = self._get_transaction_selection_form()
        self._select_credit_card(form, cardid)
        self._select_all_transactions_from(form, from_date, to_date)
        br.submit()

    def get_transaction_csv(self):
        """
        Returns a file-like object which contains the CSV data,
        selected by previous calls.

        @return file-like response
        """
        logger.info("Requesting CSV data...")
        self.br.follow_link(url_regex='csv')
        return self.br.response().read()

class DkbConverter(object):
    """
    A DKB transaction CSV to QIF converter

    Tested with GnuCash
    """

    # The financial software's target account (such as Aktiva:VISA)
    DEFAULT_CATEGORY = None

    # QIF-internal card name
    CREDIT_CARD_NAME = 'VISA'

    # input charset
    INPUT_CHARSET = 'latin1'

    # QIF output charset
    OUTPUT_CHARSET = 'utf-8'

    # Length of the pre-amble (non-CSV headers), including the
    # CSV head line
    SKIP_LINES = 8

    # Column Definitions: Which values can be found in which columns?
    COL_DATE = 1
    COL_VALUTA_DATE = 2
    COL_DESC = 3
    COL_VALUE = 4
    COL_INFO = 5

    # Number of fields for the line to be recognized as a valid
    # transaction line:
    REQUIRED_FIELDS = 5

    def __init__(self, csv_text, default_category=None, cc_name=None):
        """
        Constructor

        @param str csv_text
        @param str default_category:
            Category in your financial software
            (an account such as Aktiva:Visa)
        """
        self.csv_text = (csv_text
            .decode(self.INPUT_CHARSET)
            .encode(self.OUTPUT_CHARSET))
        self.DEFAULT_CATEGORY = default_category
        self.CREDIT_CARD_NAME = cc_name or 'VISA'

    def format_date(self, line):
        """
        Extracts the date from the given line and
        converts it from DD.MM.YYYY to MM/DD/YYYY

        @param list line
        @return str
        """
        return re.sub('.*?(\d{1,2})\.(\d{1,2})\.(\d{2,4}).*?', r'\2/\1/\3',
            line[self.COL_VALUTA_DATE])

    def format_value(self, line):
        """
        Extracts the value (such as 3,00 or -100,00) from the given
        line, removes any dots and replaces the comma by a dot.

        @param list line
        @return str
        """
        return (line[self.COL_VALUE]
            .strip()
            .replace('.', '') # 1.000 -> 1000
            .replace(',', '.')) # 0,83 -> 0.83

    def format_description(self, line):
        """
        Extracts the description from the given line and strips
        any whitespace.

        @param list line
        @return str
        """
        return line[self.COL_DESC].strip()

    def format_info(self, line):
        """
        Extracts any additional info (such as different currencies)
        from the given line and strips any whitespace.

        @param list line
        @return str
        """
        return line[self.COL_INFO].strip()

    def get_category(self, line):
        """
        Returns the best-fitting category for the given line.
        Currently, we always return the default category, but this would
        be the place for guessing algorithms.

        @param list line
        @return str
        """
        return self.DEFAULT_CATEGORY

    def get_qif_lines(self):
        """
        Does the actual CSV to QIF conversion and returns an iterator
        over all required QIF lines.
        No line separator is included.

        @return iterator
        """
        logger.info("Running csv->qif conversion...")
        yield '!Account'
        yield 'N' + self.CREDIT_CARD_NAME
        yield '^'
        yield '!Type:Bank'
        lines = self.csv_text.split('\n')
        reader = csv.reader(lines, delimiter=";")
        for x in xrange(self.SKIP_LINES):
            reader.next()
        for line in reader:
            if len(line) < self.REQUIRED_FIELDS:
                continue
            yield 'D%s' % self.format_date(line)
            yield 'T%s' % self.format_value(line)
            yield 'M%s' % self.format_description(line)
            if line[self.COL_INFO].strip():
                yield 'M%s' % self.format_info(line)
            category = self.get_category(line)
            if category:
                yield 'L%s' % category
            yield '^'

    def export_to(self, path):
        """
        Writes the QIF version of the already stored csv text to the
        given path.

        @param str path
        """
        logger.info("Exporting qif to %s", path)
        with open(path, "wb") as f:
            for line in self.get_qif_lines():
                f.write(line + "\n")

if __name__ == '__main__':
    from getpass import getpass
    from argparse import ArgumentParser
    from datetime import date

    logging.basicConfig(level=logging.DEBUG)

    cli = ArgumentParser()
    cli.add_argument("--userid",
        help="Your user id (same as used for login)")
    cli.add_argument("--cardid",
        help="Last 4 digits of your card number")
    cli.add_argument("--output", "-o",
        help="Output path (QIF)")
    cli.add_argument("--qif-account",
        help="Default QIF account name (e.g. Aktiva:VISA)")
    cli.add_argument("--from-date",
        help="Export transactions as of... (DD.MM.YYYY)")
    cli.add_argument("--to-date",
        help="Export transactions until... (DD.MM.YYYY)",
        default=date.today().strftime('%d.%m.%Y'))
    args = cli.parse_args()
    if not args.userid:
        cli.error("Please specify a valid user id")
    if not args.cardid:
        cli.error("Please specify a valid card id")

    def is_valid_date(date):
        return date and bool(re.match('^\d{1,2}\.\d{1,2}\.\d{2,5}\Z', date))

    from_date = args.from_date
    while not is_valid_date(from_date):
        from_date = raw_input("Start time: ")
    if not is_valid_date(args.to_date):
        cli.error("Please specify a valid end time")
    if not args.output:
        cli.error("Please specify a valid output path")

    pin = ""
    while not pin.strip():
        pin = getpass('PIN: ')

    fetcher = DkbScraper()

    if DEBUG:
        logger = logging.getLogger("mechanize")
        logger.addHandler(logging.StreamHandler(sys.stdout))
        logger.setLevel(logging.INFO)
        #fetcher.br.set_debug_http(True)
        fetcher.br.set_debug_responses(True)
        #fetcher.br.set_debug_redirects(True)

    fetcher.login(args.userid, pin)
    fetcher.credit_card_transactions_overview()
    fetcher.select_transactions(args.cardid, from_date, args.to_date)
    csv_text = fetcher.get_transaction_csv()

    dkb2qif = DkbConverter(csv_text, cc_name=args.qif_account)
    dkb2qif.export_to(args.output)

# Testing
# =======
# python -m unittest dkb
# test_fetcher will fail unless you manually create test data, see below

import unittest
class TestDkb(unittest.TestCase):
    def test_csv(self):
        text = open("tests/example.csv", "rb").read()
        c = DkbConverter(text)
        c.export_to("/tmp/output.qif")

    def test_fetcher(self):
        # sorry, this test relies on private data, but I'll point out
        # how to create it:
        # - download the login form to loginform.html
        # - download the page after login, modify loginform.html to
        #   POST to this file instead of the original URL
        # - do the same for
        #     * the 'Kreditkartenumsätze' page,
        #     * the page after selecting a card and a time frame
        # - set up some lightweight web server (such as lighttpd) to
        #   serve these files and change BASEURL below accordingly
        # - this is also helpful if the web site changes and you have
        #   to adapt this code
        f = DkbScraper()
        f.BASEURL = "http://localhost:8000/loginform.html"
        f.br.set_debug_http(True)
        #f.br.set_debug_responses(True)
        f.br.set_debug_redirects(True)
        logger = logging.getLogger("mechanize")
        logger.addHandler(logging.StreamHandler(sys.stdout))
        logger.setLevel(logging.INFO)
        f.login("test", "1234")
        f.credit_card_transactions_overview()
        f.select_transactions("5678", "01.01.2013", "01.09.2013")
        print f.get_transaction_csv()
<commit_msg>clarified shebang line<commit_after>#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# DKB Credit card transaction QIF exporter
# Copyright (C) 2013 Christian Hoffmann <mail@hoffmann-christian.info>
#
# Inspired by Jens Herrmann <jens.herrmann@qoli.de>,
# but written using modern tools (argparse, csv reader, mechanize,
# BeautifulSoup)
#
# 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/>.

import re
import csv
import sys
import logging
from bs4 import BeautifulSoup
from mechanize import Browser

DEBUG = False

logger = logging.getLogger(__name__)

class DkbScraper(object):
    BASEURL = "https://banking.dkb.de/dkb/-"

    def __init__(self):
        self.br = Browser()

    def login(self, userid, pin):
        """
        Create a new session by submitting the login form

        @param str userid
        @param str pin
        """
        logger.info("Starting login as user %s...", userid)
        br = self.br

        # we are not a spider, so let's ignore robots.txt...
        br.set_handle_robots(False)

        # Although we have to handle a meta refresh, we disable it here
        # since mechanize seems to be buggy and will be stuck in a
        # long (infinite?) sleep() call
        br.set_handle_refresh(False)

        br.open(self.BASEURL + '?$javascript=disabled')

        # select login form:
        br.form = list(br.forms())[0]

        br.set_all_readonly(False)
        br.form["j_username"] = userid
        br.form["j_password"] = pin
        br.form["browserName"] = "Firefox"
        br.form["browserVersion"] = "40"
        br.form["screenWidth"] = "1000"
        br.form["screenHeight"] = "800"
        br.form["osName"] = "Windows"
        br.submit()
        br.open(self.BASEURL + "?$javascript=disabled")

    def credit_card_transactions_overview(self):
        """
        Navigates the internal browser state to the credit card
        transaction overview menu
        """
        logger.info("Navigating to 'Kreditkartenumsätze'...")
        br = self.br
        overview_html = BeautifulSoup(br.response().read())
        for link in br.links():
            if re.search("Kreditkartenums.*tze", link.text, re.I):
                br.follow_link(link)
                return
            if 'weitergeleitet' in link.text:
                br.follow_link(link)
            if link.text == 'here':
                br.follow_link(text="here")
        raise RuntimeError("Unable to find link 'Kreditkartenumsätze' -- "
            "Maybe the login went wrong?")

    def _get_transaction_selection_form(self):
        """
        Internal.

        Returns the transaction selection form object (mechanize)
        """
        for form in self.br.forms():
            try:
                form.find_control(name="slCreditCard")
                return form
            except Exception:
                continue

        raise RuntimeError("Unable to find transaction selection form")

    def _select_all_transactions_from(self, form, from_date, to_date):
        """
        Internal.

        Checks the radio box "Alle Umsätze vom" and populates the
        "from" and "to" with the given values.

        @param mechanize.HTMLForm form
        @param str from_date dd.mm.YYYY
        @param str to_date dd.mm.YYYY
        """
        try:
            radio_ctrl = form.find_control("searchPeriod")
        except Exception:
            raise RuntimeError("Unable to find search period radio box")

        all_transactions_item = None
        for item in radio_ctrl.items:
            for label in item.get_labels():
                if re.search('Alle Ums.*tze.*', label.text, re.I):
                    all_transactions_item = item
                    break

        if not all_transactions_item:
            raise RuntimeError(
                "Unable to find 'Alle Umsätze vom' radio box")

        form[radio_ctrl.name] = [all_transactions_item.name]

        try:
            from_item = form.find_control(name="postingDate")
        except Exception:
            raise RuntimeError("Unable to find 'ab' date field")

        from_item.value = from_date

        try:
            to_item = form.find_control(name="toPostingDate")
        except Exception:
            raise RuntimeError("Unable to find 'to' date field")

        to_item.value = to_date

    def _select_credit_card(self, form, cardid):
        """
        Internal.

        Selects the correct credit card from the dropdown menu in the
        transaction selection form.

        @param mechanize.HTMLForm form
        @param str cardid: last 4 digits of the relevant card number
        """
        try:
            cc_list = form.find_control(name="slCreditCard")
        except Exception:
            raise RuntimeError("Unable to find credit card selection form")

        for item in cc_list.get_items():
            # find right credit card...
            for label in item.get_labels():
                pattern = r'\b\S{12}(?<=%s)\b' % re.escape(cardid)
                if re.search(pattern, label.text, re.I):
                    form[cc_list.name] = [item.name]
                    return

        raise RuntimeError("Unable to find the right credit card")

    def select_transactions(self, cardid, from_date, to_date):
        """
        Changes the current view to show all transactions between
        from_date and to_date for the credit card identified by the
        given card id.

        @param str cardid: last 4 digits of your credit card's number
        @param str from_date dd.mm.YYYY
        @param str to_date dd.mm.YYYY
        """
        br = self.br
        logger.info("Selecting transactions in time frame %s - %s...",
            from_date, to_date)

        br.form = form = self._get_transaction_selection_form()
        self._select_credit_card(form, cardid)
        self._select_all_transactions_from(form, from_date, to_date)
        br.submit()

    def get_transaction_csv(self):
        """
        Returns a file-like object which contains the CSV data,
        selected by previous calls.

        @return file-like response
        """
        logger.info("Requesting CSV data...")
        self.br.follow_link(url_regex='csv')
        return self.br.response().read()

class DkbConverter(object):
    """
    A DKB transaction CSV to QIF converter

    Tested with GnuCash
    """

    # The financial software's target account (such as Aktiva:VISA)
    DEFAULT_CATEGORY = None

    # QIF-internal card name
    CREDIT_CARD_NAME = 'VISA'

    # input charset
    INPUT_CHARSET = 'latin1'

    # QIF output charset
    OUTPUT_CHARSET = 'utf-8'

    # Length of the pre-amble (non-CSV headers), including the
    # CSV head line
    SKIP_LINES = 8

    # Column Definitions: Which values can be found in which columns?
    COL_DATE = 1
    COL_VALUTA_DATE = 2
    COL_DESC = 3
    COL_VALUE = 4
    COL_INFO = 5

    # Number of fields for the line to be recognized as a valid
    # transaction line:
    REQUIRED_FIELDS = 5

    def __init__(self, csv_text, default_category=None, cc_name=None):
        """
        Constructor

        @param str csv_text
        @param str default_category:
            Category in your financial software
            (an account such as Aktiva:Visa)
        """
        self.csv_text = (csv_text
            .decode(self.INPUT_CHARSET)
            .encode(self.OUTPUT_CHARSET))
        self.DEFAULT_CATEGORY = default_category
        self.CREDIT_CARD_NAME = cc_name or 'VISA'

    def format_date(self, line):
        """
        Extracts the date from the given line and
        converts it from DD.MM.YYYY to MM/DD/YYYY

        @param list line
        @return str
        """
        return re.sub('.*?(\d{1,2})\.(\d{1,2})\.(\d{2,4}).*?', r'\2/\1/\3',
            line[self.COL_VALUTA_DATE])

    def format_value(self, line):
        """
        Extracts the value (such as 3,00 or -100,00) from the given
        line, removes any dots and replaces the comma by a dot.

        @param list line
        @return str
        """
        return (line[self.COL_VALUE]
            .strip()
            .replace('.', '') # 1.000 -> 1000
            .replace(',', '.')) # 0,83 -> 0.83

    def format_description(self, line):
        """
        Extracts the description from the given line and strips
        any whitespace.

        @param list line
        @return str
        """
        return line[self.COL_DESC].strip()

    def format_info(self, line):
        """
        Extracts any additional info (such as different currencies)
        from the given line and strips any whitespace.

        @param list line
        @return str
        """
        return line[self.COL_INFO].strip()

    def get_category(self, line):
        """
        Returns the best-fitting category for the given line.
        Currently, we always return the default category, but this would
        be the place for guessing algorithms.

        @param list line
        @return str
        """
        return self.DEFAULT_CATEGORY

    def get_qif_lines(self):
        """
        Does the actual CSV to QIF conversion and returns an iterator
        over all required QIF lines.
        No line separator is included.

        @return iterator
        """
        logger.info("Running csv->qif conversion...")
        yield '!Account'
        yield 'N' + self.CREDIT_CARD_NAME
        yield '^'
        yield '!Type:Bank'
        lines = self.csv_text.split('\n')
        reader = csv.reader(lines, delimiter=";")
        for x in xrange(self.SKIP_LINES):
            reader.next()
        for line in reader:
            if len(line) < self.REQUIRED_FIELDS:
                continue
            yield 'D%s' % self.format_date(line)
            yield 'T%s' % self.format_value(line)
            yield 'M%s' % self.format_description(line)
            if line[self.COL_INFO].strip():
                yield 'M%s' % self.format_info(line)
            category = self.get_category(line)
            if category:
                yield 'L%s' % category
            yield '^'

    def export_to(self, path):
        """
        Writes the QIF version of the already stored csv text to the
        given path.

        @param str path
        """
        logger.info("Exporting qif to %s", path)
        with open(path, "wb") as f:
            for line in self.get_qif_lines():
                f.write(line + "\n")

if __name__ == '__main__':
    from getpass import getpass
    from argparse import ArgumentParser
    from datetime import date

    logging.basicConfig(level=logging.DEBUG)

    cli = ArgumentParser()
    cli.add_argument("--userid",
        help="Your user id (same as used for login)")
    cli.add_argument("--cardid",
        help="Last 4 digits of your card number")
    cli.add_argument("--output", "-o",
        help="Output path (QIF)")
    cli.add_argument("--qif-account",
        help="Default QIF account name (e.g. Aktiva:VISA)")
    cli.add_argument("--from-date",
        help="Export transactions as of... (DD.MM.YYYY)")
    cli.add_argument("--to-date",
        help="Export transactions until... (DD.MM.YYYY)",
        default=date.today().strftime('%d.%m.%Y'))
    args = cli.parse_args()
    if not args.userid:
        cli.error("Please specify a valid user id")
    if not args.cardid:
        cli.error("Please specify a valid card id")

    def is_valid_date(date):
        return date and bool(re.match('^\d{1,2}\.\d{1,2}\.\d{2,5}\Z', date))

    from_date = args.from_date
    while not is_valid_date(from_date):
        from_date = raw_input("Start time: ")
    if not is_valid_date(args.to_date):
        cli.error("Please specify a valid end time")
    if not args.output:
        cli.error("Please specify a valid output path")

    pin = ""
    while not pin.strip():
        pin = getpass('PIN: ')

    fetcher = DkbScraper()

    if DEBUG:
        logger = logging.getLogger("mechanize")
        logger.addHandler(logging.StreamHandler(sys.stdout))
        logger.setLevel(logging.INFO)
        #fetcher.br.set_debug_http(True)
        fetcher.br.set_debug_responses(True)
        #fetcher.br.set_debug_redirects(True)

    fetcher.login(args.userid, pin)
    fetcher.credit_card_transactions_overview()
    fetcher.select_transactions(args.cardid, from_date, args.to_date)
    csv_text = fetcher.get_transaction_csv()

    dkb2qif = DkbConverter(csv_text, cc_name=args.qif_account)
    dkb2qif.export_to(args.output)

# Testing
# =======
# python -m unittest dkb
# test_fetcher will fail unless you manually create test data, see below

import unittest
class TestDkb(unittest.TestCase):
    def test_csv(self):
        text = open("tests/example.csv", "rb").read()
        c = DkbConverter(text)
        c.export_to("/tmp/output.qif")

    def test_fetcher(self):
        # sorry, this test relies on private data, but I'll point out
        # how to create it:
        # - download the login form to loginform.html
        # - download the page after login, modify loginform.html to
        #   POST to this file instead of the original URL
        # - do the same for
        #     * the 'Kreditkartenumsätze' page,
        #     * the page after selecting a card and a time frame
        # - set up some lightweight web server (such as lighttpd) to
        #   serve these files and change BASEURL below accordingly
        # - this is also helpful if the web site changes and you have
        #   to adapt this code
        f = DkbScraper()
        f.BASEURL = "http://localhost:8000/loginform.html"
        f.br.set_debug_http(True)
        #f.br.set_debug_responses(True)
        f.br.set_debug_redirects(True)
        logger = logging.getLogger("mechanize")
        logger.addHandler(logging.StreamHandler(sys.stdout))
        logger.setLevel(logging.INFO)
        f.login("test", "1234")
        f.credit_card_transactions_overview()
        f.select_transactions("5678", "01.01.2013", "01.09.2013")
        print f.get_transaction_csv()
<|endoftext|>


<commit_before>
from jamenson.runtime.multimethod import defmethod
from jamenson.runtime.atypes import anytype

from . import algebra as A

class DNEType(A.AlgebraBase):
    def __str__(self):
        return 'd.n.e.'

dne = DNEType()

@defmethod(A.mm_unop_base, [DNEType])
def meth(op):
    return dne

@defmethod(A.mm_binop_base, [DNEType, anytype])
@defmethod(A.mm_binop_base, [anytype, DNEType])
def meth(a, b):
    return dne
<commit_msg>Added doc string<commit_after>"""Does Not Exist
   Object to signify answer doesn't exist (e.g. division by zero)
"""

from jamenson.runtime.multimethod import defmethod
from jamenson.runtime.atypes import anytype

from . import algebra as A

class DNEType(A.AlgebraBase):
    def __str__(self):
        return 'd.n.e.'

dne = DNEType()

@defmethod(A.mm_unop_base, [DNEType])
def meth(op):
    return dne

@defmethod(A.mm_binop_base, [DNEType, anytype])
@defmethod(A.mm_binop_base, [anytype, DNEType])
def meth(a, b):
    return dne
<|endoftext|>


<commit_before>import ConfigParser
import codecs
import glob
import string
import os

from lxml import etree
from csv_utils import UnicodeWriter

TEI = {'ns': 'http://www.tei-c.org/ns/1.0'}
NL = 'nl'
MARKUP = u'**{}**'

def pp_to_text(pp):
    """
    Turns a present perfect into text.
    """
    return ' '.join([part for (part, is_verb) in pp if is_verb])

def get_adjacent_line_number(segment_number, i):
    """
    Returns the next segment number + i.
    """
    split = segment_number.split('s')
    adj = int(split[1]) + i
    return split[0] + 's' + str(adj)

def get_marked_sentence(sentence, pp):
    """
    Marks the present perfect in a full sentence.
    TODO: this is a bit iffy, another idea could be to compose the sentence from the remaining siblings
    """
    # To find the pp in the full text, just join all the parts of the pp
    pp_text = ' '.join([part for (part, _) in pp])

    # For the replacement, mark the verbs with the MARKUP
    pp_verbs = [part for (part, is_verb) in pp if is_verb]
    if len(pp) == len(pp_verbs):
        marked_pp = MARKUP.format(pp_text)
    else:
        marked_pp = ' '.join([MARKUP.format(part) if is_verb else part for (part, is_verb) in pp])

    return sentence.replace(pp_text, marked_pp)

class PerfectExtractor:
    def __init__(self, language_from, languages_to):
        self.l_from = language_from
        self.l_to = languages_to

        # Read the config
        config = ConfigParser.RawConfigParser()
        config.readfp(codecs.open('dpc.cfg', 'r', 'utf8'))
        self.config = config

        # Read the list of verbs that use 'to be' as auxiliary verb
        self.aux_be_list = []
        if self.config.get(self.l_from, 'lexical_bound'):
            with codecs.open(self.l_from + '_aux_be.txt', 'rb', 'utf-8') as lexicon:
                self.aux_be_list = lexicon.read().split()

    def is_nl(self):
        """
        Returns whether the current from language is Dutch (as integer).
        """
        return int(self.l_from == NL)

    def get_translated_lines(self, document, language_to, segment_number):
        """
        Returns the translated segment numbers (could be multiple) for a segment number in the original text.

        The translation document file format either ends with nl-en-tei.xml or nl-fr-tei.xml.

        An alignment line looks like this:
            <link type="A: 1-1" targets="p1.s1; p1.s1"/>
        To get from NL to EN/FR, we have to find the segment number in the targets attribute BEFORE the semicolon.
        For the reverse pattern, we have to find the segment number in the targets attribute AFTER the semicolon.

        This function supports 1-to-2 alignments, as it will return the translated lines as a list.

        TODO: deal with 2-to-1 alignments as well here.
        """
        not_nl = language_to if language_to != NL else self.l_from
        alignment_file = document + NL + '-' + not_nl + '-tei.xml'

        result = []
        if os.path.isfile(alignment_file):
            alignment_tree = etree.parse(alignment_file)
            for link in alignment_tree.xpath('//ns:link', namespaces=TEI):
                targets = link.get('targets').split('; ')
                if segment_number in targets[1 - self.is_nl()].split(' '):
                    result = targets[self.is_nl()].split(' ')
                    break

        return result

    def get_line_by_number(self, tree, language_to, segment_number):
        """
        Returns the line for a segment number.
        TODO: handle more than one here? => bug
        """
        sentence = '-'
        pp = None

        line = tree.xpath('//ns:s[@n="' + segment_number + '"]', namespaces=TEI)
        if line:
            s = line[0]
            sentence = s.getprevious().text
            for e in s.xpath(self.config.get(language_to, 'xpath'), namespaces=TEI):
                pp = self.check_present_perfect(e, language_to)
                if pp:
                    sentence = get_marked_sentence(s.getprevious().text, pp)
                    break

        return sentence, pp

    def get_original_language(self, document):
        """
        Returns the original language for a document.
        """
        metadata_tree = etree.parse(document + self.l_from + '-mtd.xml')
        return metadata_tree.getroot().find('metaTrans').find('Original').get('lang')

    def is_lexically_bound(self, aux_verb, perfect):
        """
        Checks if the perfect is lexically bound to the auxiliary verb.
        If not, we are not dealing with a present perfect here.
        """
        aux_be = self.config.get(self.l_from, 'lexical_bound')

        # If lexical bounds do not exist or we're dealing with an auxiliary verb that is unbound, return True
        if not aux_be or aux_verb.get('lemma') != aux_be:
            return True
        # Else, check whether the perfect is in the list of bound verbs
        else:
            return perfect.get('lemma') in self.aux_be_list

    def check_present_perfect(self, element, language, check_ppc=True):
        """
        Checks whether this element is the start of a present perfect (or pp continuous).
        If it is, the present perfect is returned as a list.
        If not, None is returned.
        """
        perfect_tag = self.config.get(language, 'perfect_tag')
        check_ppc = check_ppc and self.config.getboolean(language, 'ppc')
        ppc_lemma = self.config.get(language, 'ppc_lemma')
        stop_tags = tuple(self.config.get(language, 'stop_tags').split(','))

        # Collect all parts of the present perfect as tuples with text and whether it's verb
        pp = [(element.text, True)]

        is_pp = False
        for sibling in element.itersiblings():
            # If the tag of the sibling is the perfect tag, we found a present perfect!
            if sibling.get('ana') == perfect_tag:
                # Check if the sibling is lexically bound to the auxiliary verb
                if not self.is_lexically_bound(element, sibling):
                    break
                pp.append((sibling.text, True))
                is_pp = True
                # ... now check whether this is a present perfect continuous (by recursion)
                if check_ppc and sibling.get('lemma') == ppc_lemma:
                    ppc = self.check_present_perfect(sibling, language, False)
                    if ppc:
                        pp.extend(ppc[1:])
                break
            # Stop looking at punctuation or stop tags
            elif sibling.text in string.punctuation or sibling.get('ana').startswith(stop_tags):
                break
            # No break? Then add as a non-verb part
            else:
                pp.append((sibling.text, False))

        return pp if is_pp else None

    def find_translated_present_perfects(self, document, language_to, translated_lines):
        translated_pps = []
        lines = []

        if translated_lines:
            translated_tree = etree.parse(document + language_to + '-tei.xml')
            for t in translated_lines:
                #f.write(get_line_by_number(translated_tree, get_adjacent_line_number(t, -1)) + '\n')
                translation, translated_pp = self.get_line_by_number(translated_tree, language_to, t)
                translated_pp = pp_to_text(translated_pp) if translated_pp else '-'

                translated_pps.append(translated_pp)
                lines.append(translation)
                #f.write(get_line_by_number(translated_tree, get_adjacent_line_number(t, 1)) + '\n')

        return translated_pps, lines

    def process_folder(self, dir_name):
        """
        Creates a result file and processes each file in a folder.
        """
        result_file = '-'.join([dir_name, self.l_from]) + '.csv'
        with open(result_file, 'wb') as f:
            f.write(u'\uFEFF'.encode('utf-8'))  # the UTF-8 BOM to hint Excel we are using that...
            csv_writer = UnicodeWriter(f, delimiter=';')

            header = [
                'document',
                'original_language',
                'present perfect ' + self.l_from,
                self.l_from]
            for language in self.l_to:
                header.append('present perfect ' + language)
                header.append(language)
            csv_writer.writerow(header)

            for filename in glob.glob(dir_name + '/*[0-9]-' + self.l_from + '-tei.xml'):
                results = self.process_file(filename)
                csv_writer.writerows(results)

    def process_file(self, filename):
        """
        Processes a single file.
        """
        document = filename.split(self.l_from + '-tei.xml')[0]
        results = []

        tree = etree.parse(filename)
        for e in tree.xpath('//' + self.config.get(self.l_from, 'xpath'), namespaces=TEI):
            pp = self.check_present_perfect(e, self.l_from)

            if pp:
                result = [document[:-1], self.get_original_language(document)]

                result.append(pp_to_text(pp))
                #words_between = [part for (part, is_verb) in pp if not is_verb]
                #result.append(str(len(words_between)))

                # Write the complete segment with mark-up
                marked_sentence = get_marked_sentence(e.getparent().getprevious().text, pp)
                result.append(marked_sentence)

                # Find the translated lines
                segment_number = e.getparent().getparent().get('n')[4:]
                for language_to in self.l_to:
                    translated_lines = self.get_translated_lines(document, language_to, segment_number)
                    translated_present_perfect, translated_marked_sentence = self.find_translated_present_perfects(document, language_to, translated_lines)
                    result.append('\n'.join(translated_present_perfect))
                    result.append('\n'.join(translated_marked_sentence))

                results.append(result)

        return results

#for root, dirs, files in os.walk(os.getcwd()):
#    for d in dirs:
#        process_folder(d)
        #break
#process_folder('bal')

if __name__ == "__main__":
    en_extractor = PerfectExtractor('en', ['nl', 'fr'])
    en_extractor.process_folder('data/bal_small')
    nl_extractor = PerfectExtractor('nl', ['en'])
    nl_extractor.process_folder('data/bal_small')
    #fr_extractor = PerfectExtractor('fr', 'nl')
    #fr_extractor.process_folder('data/mok')
<commit_msg>Fixed alignment for EN to FR and reversed<commit_after>import ConfigParser
import codecs
import glob
import string
import os

from lxml import etree
from csv_utils import UnicodeWriter

TEI = {'ns': 'http://www.tei-c.org/ns/1.0'}
NL = 'nl'
MARKUP = u'**{}**'

def pp_to_text(pp):
    """
    Turns a present perfect into text.
    """
    return ' '.join([part for (part, is_verb) in pp if is_verb])

def get_adjacent_line_number(segment_number, i):
    """
    Returns the next segment number + i.
    """
    split = segment_number.split('s')
    adj = int(split[1]) + i
    return split[0] + 's' + str(adj)

def get_marked_sentence(sentence, pp):
    """
    Marks the present perfect in a full sentence.
    TODO: this is a bit iffy, another idea could be to compose the sentence from the remaining siblings
    """
    # To find the pp in the full text, just join all the parts of the pp
    pp_text = ' '.join([part for (part, _) in pp])

    # For the replacement, mark the verbs with the MARKUP
    pp_verbs = [part for (part, is_verb) in pp if is_verb]
    if len(pp) == len(pp_verbs):
        marked_pp = MARKUP.format(pp_text)
    else:
        marked_pp = ' '.join([MARKUP.format(part) if is_verb else part for (part, is_verb) in pp])

    return sentence.replace(pp_text, marked_pp)

class PerfectExtractor:
    def __init__(self, language_from, languages_to):
        self.l_from = language_from
        self.l_to = languages_to

        # Read the config
        config = ConfigParser.RawConfigParser()
        config.readfp(codecs.open('dpc.cfg', 'r', 'utf8'))
        self.config = config

    def is_nl(self):
        """
        Returns whether the current from language is Dutch (as integer).
        """
        return int(self.l_from == NL)

    def get_translated_lines(self, document, language_from, language_to, segment_number):
        """
        Returns the translated segment numbers (could be multiple) for a segment number in the original text.

        The translation document file format either ends with nl-en-tei.xml or nl-fr-tei.xml.

        An alignment line looks like this:
            <link type="A: 1-1" targets="p1.s1; p1.s1"/>

        To get from NL to EN/FR, we have to find the segment number in the targets attribute BEFORE the semicolon.
        For the reverse pattern, we have to find the segment number in the targets attribute AFTER the semicolon.

        To get from EN to FR or from FR to EN, we have to use NL as an in between language.

        This function supports 1-to-2 alignments, as it will return the translated lines as a list.

        TODO: deal with 2-to-2 and 2-to-1 alignments as well here.
        """
        result = []

        if NL in [language_from, language_to]:
            not_nl = language_to if language_to != NL else language_from
            alignment_file = document + NL + '-' + not_nl + '-tei.xml'

            if os.path.isfile(alignment_file):
                alignment_tree = etree.parse(alignment_file)
                for link in alignment_tree.xpath('//ns:link', namespaces=TEI):
                    targets = link.get('targets').split('; ')
                    if segment_number in targets[1 - int(language_from == NL)].split(' '):
                        result = targets[int(language_from == NL)].split(' ')
                        break
        else:
            lookup = self.get_translated_lines(document, language_from, NL, segment_number)
            for lookup_number in lookup:
                lines = self.get_translated_lines(document, NL, language_to, lookup_number)
                result.extend(lines)

        return set(result)

    def get_line_by_number(self, tree, language_to, segment_number):
        """
        Returns the line for a segment number.
        TODO: handle more than one here? => bug
        """
        sentence = '-'
        pp = None

        line = tree.xpath('//ns:s[@n="' + segment_number + '"]', namespaces=TEI)
        if line:
            s = line[0]
            sentence = s.getprevious().text
            for e in s.xpath(self.config.get(language_to, 'xpath'), namespaces=TEI):
                pp = self.check_present_perfect(e, language_to)
                if pp:
                    sentence = get_marked_sentence(s.getprevious().text, pp)
                    break

        return sentence, pp

    def get_original_language(self, document):
        """
        Returns the original language for a document.
        """
        metadata_tree = etree.parse(document + self.l_from + '-mtd.xml')
        return metadata_tree.getroot().find('metaTrans').find('Original').get('lang')

    def is_lexically_bound(self, language, aux_verb, perfect):
        """
        Checks if the perfect is lexically bound to the auxiliary verb.
        If not, we are not dealing with a present perfect here.
        """
        aux_be = self.config.get(language, 'lexical_bound')

        # Read the list of verbs that use 'to be' as auxiliary verb
        # TODO: read this only once for performance
        aux_be_list = []
        if aux_be:
            with codecs.open(language + '_aux_be.txt', 'rb', 'utf-8') as lexicon:
                aux_be_list = lexicon.read().split()

        # If lexical bounds do not exist or we're dealing with an auxiliary verb that is unbound, return True
        if not aux_be or aux_verb.get('lemma') != aux_be:
            return True
        # Else, check whether the perfect is in the list of bound verbs
        else:
            return perfect.get('lemma') in aux_be_list

    def check_present_perfect(self, element, language, check_ppc=True):
        """
        Checks whether this element is the start of a present perfect (or pp continuous).
        If it is, the present perfect is returned as a list.
        If not, None is returned.
        """
        perfect_tag = self.config.get(language, 'perfect_tag')
        check_ppc = check_ppc and self.config.getboolean(language, 'ppc')
        ppc_lemma = self.config.get(language, 'ppc_lemma')
        stop_tags = tuple(self.config.get(language, 'stop_tags').split(','))

        # Collect all parts of the present perfect as tuples with text and whether it's verb
        pp = [(element.text, True)]

        is_pp = False
        for sibling in element.itersiblings():
            # If the tag of the sibling is the perfect tag, we found a present perfect!
            if sibling.get('ana') == perfect_tag:
                # Check if the sibling is lexically bound to the auxiliary verb
                if not self.is_lexically_bound(language, element, sibling):
                    break
                pp.append((sibling.text, True))
                is_pp = True
                # ... now check whether this is a present perfect continuous (by recursion)
                if check_ppc and sibling.get('lemma') == ppc_lemma:
                    ppc = self.check_present_perfect(sibling, language, False)
                    if ppc:
                        pp.extend(ppc[1:])
                break
            # Stop looking at punctuation or stop tags
            elif sibling.text in string.punctuation or sibling.get('ana').startswith(stop_tags):
                break
            # No break? Then add as a non-verb part
            else:
                pp.append((sibling.text, False))

        return pp if is_pp else None

    def find_translated_present_perfects(self, document, language_to, translated_lines):
        translated_pps = []
        lines = []

        if translated_lines:
            # TODO: parse this only once for performance
            translated_tree = etree.parse(document + language_to + '-tei.xml')
            for t in translated_lines:
                #f.write(get_line_by_number(translated_tree, get_adjacent_line_number(t, -1)) + '\n')
                translation, translated_pp = self.get_line_by_number(translated_tree, language_to, t)
                translated_pp = pp_to_text(translated_pp) if translated_pp else ''

                translated_pps.append(translated_pp)
                lines.append(translation)
                #f.write(get_line_by_number(translated_tree, get_adjacent_line_number(t, 1)) + '\n')

        return translated_pps, lines

    def process_folder(self, dir_name):
        """
        Creates a result file and processes each file in a folder.
        """
        result_file = '-'.join([dir_name, self.l_from]) + '.csv'
        with open(result_file, 'wb') as f:
            f.write(u'\uFEFF'.encode('utf-8'))  # the UTF-8 BOM to hint Excel we are using that...
            csv_writer = UnicodeWriter(f, delimiter=';')

            header = [
                'document',
                'original_language',
                'present perfect ' + self.l_from,
                self.l_from]
            for language in self.l_to:
                header.append('present perfect ' + language)
                header.append(language)
            csv_writer.writerow(header)

            for filename in glob.glob(dir_name + '/*[0-9]-' + self.l_from + '-tei.xml'):
                results = self.process_file(filename)
                csv_writer.writerows(results)

    def process_file(self, filename):
        """
        Processes a single file.
        """
        document = filename.split(self.l_from + '-tei.xml')[0]
        results = []

        tree = etree.parse(filename)
        for e in tree.xpath('//' + self.config.get(self.l_from, 'xpath'), namespaces=TEI):
            pp = self.check_present_perfect(e, self.l_from)

            if pp:
                result = [document[:-1], self.get_original_language(document)]

                result.append(pp_to_text(pp))
                #words_between = [part for (part, is_verb) in pp if not is_verb]
                #result.append(str(len(words_between)))

                # Write the complete segment with mark-up
                marked_sentence = get_marked_sentence(e.getparent().getprevious().text, pp)
                result.append(marked_sentence)

                # Find the translated lines
                segment_number = e.getparent().getparent().get('n')[4:]
                for language_to in self.l_to:
                    translated_lines = self.get_translated_lines(document, self.l_from, language_to, segment_number)
                    translated_present_perfect, translated_marked_sentence = self.find_translated_present_perfects(document, language_to, translated_lines)
                    result.append('\n'.join(translated_present_perfect))
                    result.append('\n'.join(translated_marked_sentence))

                results.append(result)

        return results

#for root, dirs, files in os.walk(os.getcwd()):
#    for d in dirs:
#        process_folder(d)
        #break
#process_folder('bal')

if __name__ == "__main__":
    en_extractor = PerfectExtractor('en', ['nl', 'fr'])
    en_extractor.process_folder('data/bmm')
    nl_extractor = PerfectExtractor('nl', ['en', 'fr'])
    nl_extractor.process_folder('data/bmm')
    fr_extractor = PerfectExtractor('fr', ['nl', 'en'])
    fr_extractor.process_folder('data/bmm')
<|endoftext|>


<commit_before>from collections import namedtuple
from datetime import datetime

from parsley import makeGrammar

class Symbol(namedtuple("Symbol", "name prefix type")):
    _MARKER = object()

    def __new__(cls, name, prefix=None):
        return super(Symbol, cls).__new__(cls, name, prefix, Symbol._MARKER)

class Keyword(namedtuple("Keyword", "name prefix type")):
    _MARKER = object()

    def __new__(cls, name_or_symbol, prefix=None):
        name = name_or_symbol

        if isinstance(name_or_symbol, Symbol):
            name = name_or_symbol.name
            prefix = name_or_symbol.prefix

        return super(Keyword, cls).__new__(cls, name, prefix, Keyword._MARKER)

# XXX: jml is not convinced that it's best to decode vectors or lists to
# tuples.  Sure that grants immutability, but it seems weird.  I'd much rather
# a conversion to regular Python lists, or to some proper immutable linked
# list / vector implementation.  The best thing would be to allow us to plug
# in what we'd like these things to be decoded to, I guess.
class Vector(tuple):
    pass

TaggedValue = namedtuple("TaggedValue", "tag value")

# XXX: There needs to be a character type and a string-that-escapes-newlines
# type in order to have full roundtripping.

edn = makeGrammar(open('edn.parsley').read(),
                  {
                    'Symbol': Symbol,
                    'Keyword': Keyword,
                    'Vector': Vector,
                    'TaggedValue': TaggedValue
                  },
                  name='edn')

def loads(string):
    return edn(string).edn()

def _dump_bool(obj):
    if obj:
        return 'true'
    else:
        return 'false'

def _dump_str(obj):
    return '"%s"' % (repr(obj)[1:-1].replace('"', '\\"'),)

def _dump_symbol(obj):
    if obj.prefix:
        return ['%s/%s' % (obj.prefix, obj.name)]
    return obj.name

def _dump_keyword(obj):
    if obj.prefix:
        return [':%s/%s' % (obj.prefix, obj.name)]
    return ':' + obj.name

def _dump_list(obj):
    return ['(', map(dumps, obj), ')']

def _dump_set(obj):
    return ['#{', map(dumps, obj), '}']

def _dump_dict(obj):
    # XXX: Comma is optional.  Should there be an option?
    return ['{', [[dumps(k), dumps(v)] for k, v in obj.items()], '}']

INST = Symbol('#inst')
def _dump_inst(obj):
    return map(dumps, [INST, obj.strftime('%Y-%m-%dT%H:%M.%SZ')])

def _flatten(tokens):
    if isinstance(tokens, (list, tuple)):
        for token in tokens:
            for subtoken in _flatten(token):
                yield subtoken
    else:
        yield tokens

def _format(tokens):
    last_token = None
    open_brackets = frozenset(['{', '#{', '(', '[', None])
    close_brackets = '})]'
    for token in tokens:
        if last_token not in open_brackets and token not in close_brackets:
            yield ' '
        yield token
        last_token = token

def dumps(obj):
    # XXX: It occurs to me that the 'e' in 'edn' means that there should be a
    # way to extend this -- jml
    RULES = [
        (bool, _dump_bool),
        ((int, float), lambda x: [str(x)]),
        (str, _dump_str),
        (type(None), lambda x: ['nil']),
        (Keyword, _dump_keyword),
        (Symbol, _dump_symbol),
        ((list, tuple), _dump_list),
        ((set, frozenset), _dump_set),
        (dict, _dump_dict),
        (datetime, _dump_inst),
    ]
    for base_type, dump_rule in RULES:
        if isinstance(obj, base_type):
            tokens = dump_rule(obj)
            return ''.join(_format(_flatten(tokens)))
    raise ValueError("Cannot encode %r" % (obj,))
<commit_msg>TODOs & XXXs<commit_after>from collections import namedtuple
from datetime import datetime

from parsley import makeGrammar

class Symbol(namedtuple("Symbol", "name prefix type")):
    _MARKER = object()

    def __new__(cls, name, prefix=None):
        return super(Symbol, cls).__new__(cls, name, prefix, Symbol._MARKER)

class Keyword(namedtuple("Keyword", "name prefix type")):
    _MARKER = object()

    def __new__(cls, name_or_symbol, prefix=None):
        name = name_or_symbol

        if isinstance(name_or_symbol, Symbol):
            name = name_or_symbol.name
            prefix = name_or_symbol.prefix

        return super(Keyword, cls).__new__(cls, name, prefix, Keyword._MARKER)

# XXX: jml is not convinced that it's best to decode vectors or lists to
# tuples.  Sure that grants immutability, but it seems weird.  I'd much rather
# a conversion to regular Python lists, or to some proper immutable linked
# list / vector implementation.  The best thing would be to allow us to plug
# in what we'd like these things to be decoded to, I guess.
class Vector(tuple):
    pass

# XXX: So I guess this means we're taking
TaggedValue = namedtuple("TaggedValue", "tag value")

# XXX: There needs to be a character type and a string-that-escapes-newlines
# type in order to have full roundtripping.

edn = makeGrammar(open('edn.parsley').read(),
                  {
                    'Symbol': Symbol,
                    'Keyword': Keyword,
                    'Vector': Vector,
                    'TaggedValue': TaggedValue
                  },
                  name='edn')

def loads(string):
    return edn(string).edn()

def _dump_bool(obj):
    if obj:
        return 'true'
    else:
        return 'false'

def _dump_str(obj):
    return '"%s"' % (repr(obj)[1:-1].replace('"', '\\"'),)

def _dump_symbol(obj):
    if obj.prefix:
        return ['%s/%s' % (obj.prefix, obj.name)]
    return obj.name

def _dump_keyword(obj):
    if obj.prefix:
        return [':%s/%s' % (obj.prefix, obj.name)]
    return ':' + obj.name

def _dump_list(obj):
    return ['(', map(dumps, obj), ')']

def _dump_set(obj):
    return ['#{', map(dumps, obj), '}']

def _dump_dict(obj):
    # XXX: Comma is optional.  Should there be an option?
    return ['{', [[dumps(k), dumps(v)] for k, v in obj.items()], '}']

INST = Symbol('#inst')
def _dump_inst(obj):
    # XXX: Re-implement this in terms of taggedvalue when we've got it.
    return map(dumps, [INST, obj.strftime('%Y-%m-%dT%H:%M.%SZ')])

# XXX: It'd be interesting to see how clojure does it, but I reckon that a map
# of symbols to a read function and a write function is the best way to handle
# tagged values.  The write function would return a known out-of-band value if
# it is given a value that's not appropriate for it.
#
# Variants:
# - two maps, one for parsing, one for dumping
# - (optional?) is this a #foo? predicate included in dumping map

# XXX: Not directly tested
def _flatten(tokens):
    if isinstance(tokens, (list, tuple)):
        for token in tokens:
            for subtoken in _flatten(token):
                yield subtoken
    else:
        yield tokens

# XXX: Not directly tested
# XXX: Doesn't do commas between dict entries
def _format(tokens):
    last_token = None
    open_brackets = frozenset(['{', '#{', '(', '[', None])
    close_brackets = '})]'
    for token in tokens:
        if last_token not in open_brackets and token not in close_brackets:
            yield ' '
        yield token
        last_token = token

# XXX: Pretty printer

# XXX: Maybe a default handler for namedtuples?

def dumps(obj):
    # XXX: It occurs to me that the 'e' in 'edn' means that there should be a
    # way to extend this -- jml
    RULES = [
        (bool, _dump_bool),
        ((int, float), lambda x: [str(x)]),
        (str, _dump_str),
        (type(None), lambda x: ['nil']),
        (Keyword, _dump_keyword),
        (Symbol, _dump_symbol),
        ((list, tuple), _dump_list),
        ((set, frozenset), _dump_set),
        (dict, _dump_dict),
        (datetime, _dump_inst),
    ]
    for base_type, dump_rule in RULES:
        if isinstance(obj, base_type):
            tokens = dump_rule(obj)
            return ''.join(_format(_flatten(tokens)))
    raise ValueError("Cannot encode %r" % (obj,))
<|endoftext|>


<commit_before>from ctypes import cdll

mylib = cdll.LoadLibrary("osvrClientKit")

def OSVR_ClientContext(Structure):
    pass
def OSVR_ReturnCode(Structure):
    pass
def OSVR_ClientInterface(Structure):
    pass
def OSVR_DisplayConfigObject(Structure):
    pass

def osvrClientInit(applicationIdentifier, flags):
	mylib.osvrClientInit.argtypes = [c_char_p, c_uint32]
    mylib.osvrClientInit.restype = OSVR_ClientContext
    rval = mylib.osvrClientInit(c_char_p(applicationIdentifier), c_uint32(flags))
	return rval

def osvrClientUpdate(ctx):
    mylib.osvrClientUpdate.argtypes = [OSVR_ClientContext]
	mylib.osvrClientUpdate.restype = OSVR_ReturnCode
    rval = mylib.osvrClientUpdate(ctx)
	return rval

def osvrClientCheckStatus(ctx):
    mylib.osvrClientCheckStatus.argtypes = [OSVR_ClientContext]
    mylib.osvrClientCheckStatus.restype = OSVR_ReturnCode
	rval = mylib.osvrClientCheckStatus(ctx)
	return rval

def osvrClientShutdown(ctx):
    mylib.osvrClientShutdown.argtypes = [OSVR_ClientContext]
    mylib.osvrClientShutdown.restype = OSVR_ReturnCode
	rval = mylib.osvrClientShutdown(ctx)
	return rval

def osvrClientGetInterface(ctx, path, iface):
    mylib.osvrClientGetInterface.argtypes = [OSVR_ClientContext, c_char_p, pointer(OSVR_ClientInterface)]
    mylib.osvrClientGetInterace.restype = OSVR_ReturnCode
	return mylib.osvrClientGetInterface(ctx, c_char_p(path), iface)

def osvrClientFreeInterface(ctx, iface):
    mylib.osvrClientFreeInterface.argtypes = [OSVR_ClientContext, OSVR_ClientInterface]
    mylib.osvrClientFreeInterface.restype = OSVR_ReturnCode
	return mylib.osvrClientFreeInterface(ctx, iface)

def osvrClientGetStringParameterLength(ctx, path, len):
    mylib.osvrClientGetStringParameterLength.argtypes = [OSVR_ClientContext, c_char_p, c_size_t]
    mylib.osvrClientGetStringParameterLength.restype = OSVR_ReturnCode
	return mylib.osvrGetStringParameterLength(ctx, c_char_p(path), c_size_t(len)

def osvrClientGetStringParameter(ctx, path, buf, len):
    mylib.osvrClientGetStringParameterLength.argtypes = [OSVR_ClientContext, c_char_p, c_char_p c_size_t]
    mylib.osvrClientGetStringParameterLength.restype = OSVR_ReturnCode
	return mylib.osvrClientGetStringParameter(ctx, c_char_p(path), c_char_p(buf), c_size_t(len);

def osvrClientGetDisplay(ctx, disp)
    mylib.osvrClientGetDisplay.argtypes = [OSVR_ClientContext, pointer(OSVR_DisplayConfig)]
    mylib.osvrClientGetDisplay.restype = OSVR_ReturnCode
    return mylib.osvrClientGetDisplay(ctx, disp)

def osvrClientFreeDisplay(disp)
    return mylib.osvrClientFreeDisplay(disp)

def osvrClientCheckDisplayStartup(disp)
    return mylib.osvrClientCheckDisplayStartup(disp)

def osvrClientGetNumDisplayInputs(disp, numDisplayInputs)
    return mylib.osvrClientGetNumDisplayInputs(disp, numDisplayInputs)

def osvrClientGetDisplayDimensions(disp, displayInputIndex, width, height)
    return mylib.osvrClientGetDisplayDimensions(disp, displayInputIndex, width, height)

def osvrClientGetNumViewers(disp, viewers)
    return mylib.osvrClientGetNumViewers(disp, viewers)

def osvrClientGetViewerPose(disp, viewer, pose)
    return mylib.osvrClientGetViewerPose(disp, viewer, pose)

def osvrClientGetNumEyesForViewer(disp, viewer, eyes)
    return mylib.osvrClientGetNumEyesForViewer(disp, viewer, eyes)

def osvrClientGetViewerEyePose(disp, viewer, eye, pose)
    return mylib.osvrClientGetViewerPose(disp, viewer, eye, pose)

def osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, mat)
    return mylib.osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, mat)

def osvrClientGetViewerEyeViewMatrixf(disp, viewer, eye, flags, mat)
    return mylib.osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, mat)

def osvrClientGetNumSurfacesForViewerEye(disp, viewer, eye, surfaces)
    return mylib.osvrClientGetNumSurfacesForViewerEye(disp, viewer, eye, surfaces)

def osvrClientGetRelativeViewportForViewerEyeSurface(disp, viewer, eye, surface, left, bottom, width, height)
    return mylib.osvrClientGetRelativeViewportForViewerEyeSurface(disp, viewer, eye, surface, left, bottom, width, height)

def osvrClientGetViewerEyeSurfaceDisplayInputIndex(disp, viewer, eye, surface, displayInput)
    return osvrClientGetViewerEyeSurfaceDisplayInputIndex(disp, viewer, eye, surface, displayInput)

def osvrClientGetViewerEyeSurfaceProjectionMatrixd(disp, viewer, eye, surface, near, far, flags, matrix)
    return mylib.osvrClientGetViewerEyeSurfaceProjectionMatrixd(disp, viewer, eye, surface, near, far, flags, matrix)

def osvrClientGetViewerEyeSurfaceProjectionMatrixf(disp, viewer, eye, surface, near, far, flags, matrix)
    return mylib.osvrClientGetViewerEyeSurfaceProjectionMatrixf(disp, viewer, eye, surface, near, far, flags, matrix)

def osvrClientGetViewerEyeSurfaceProjectionClippingPlanes(disp, viewer, eye, surface, left, right, bottom, top)
    return mylib.osvrClientGetViewerEyeSurfaceProjectionClippingPlanes(disp, viewer, eye, surface, left, right, bottom, top)

def osvrClientDoesViewerEyeSurfaceWantDistortion(disp, viewer, eye, surface, distortionRequested)
    return mylib.osvrClientDoesViewerEyeSurfaceWantDistortion(disp, viewer, eye, surface, distortionRequested)

def osvrClientGetViewerEyeSurfaceRadialDistortionPriority(disp, viewer, eye, surface, priority)
    return mylib.osvrClientGetViewerEyeSurfaceRadialDistortionPriority(disp, viewer, eye, surface, priority)

def osvrClientGetViewerEyeSurfaceRadialDistortion(disp, viewer, eye, surface, params)
    return mylib.osvrClientGetViewerEyeSurfaceRadialDistortion(disp, viewer, eye, surface, params)<commit_msg>set argtypes and restypes down through osvrClientGetRelativeViewportForViewerEyeSurface<commit_after>from ctypes import cdll

mylib = cdll.LoadLibrary("osvrClientKit")

def OSVR_ClientContext(Structure):
    pass
def OSVR_ReturnCode(Structure):
    pass
def OSVR_ClientInterface(Structure):
    pass
def OSVR_DisplayConfigObject(Structure):
    pass
def OSVR_DisplayDimension(Structure):
    pass
def OSVR_ViewerCount(Structure):
    pass
def OSVR_Pose3(Structure):
    pass
def OSVR_EyeCount(Structure):
    pass
def OSVR_SurfaceCount(Structure):
    pass

def osvrClientInit(applicationIdentifier, flags):
	mylib.osvrClientInit.argtypes = [c_char_p, c_uint32]
    mylib.osvrClientInit.restype = OSVR_ClientContext
    return mylib.osvrClientInit(c_char_p(applicationIdentifier), c_uint32(flags))

def osvrClientUpdate(ctx):
    mylib.osvrClientUpdate.argtypes = [OSVR_ClientContext]
	mylib.osvrClientUpdate.restype = OSVR_ReturnCode
    return mylib.osvrClientUpdate(ctx)

def osvrClientCheckStatus(ctx):
    mylib.osvrClientCheckStatus.argtypes = [OSVR_ClientContext]
    mylib.osvrClientCheckStatus.restype = OSVR_ReturnCode
	return mylib.osvrClientCheckStatus(ctx)

def osvrClientShutdown(ctx):
    mylib.osvrClientShutdown.argtypes = [OSVR_ClientContext]
    mylib.osvrClientShutdown.restype = OSVR_ReturnCode
	return mylib.osvrClientShutdown(ctx)

def osvrClientGetInterface(ctx, path, iface):
    mylib.osvrClientGetInterface.argtypes = [OSVR_ClientContext, c_char_p, pointer(OSVR_ClientInterface)]
    mylib.osvrClientGetInterace.restype = OSVR_ReturnCode
	return mylib.osvrClientGetInterface(ctx, c_char_p(path), iface)

def osvrClientFreeInterface(ctx, iface):
    mylib.osvrClientFreeInterface.argtypes = [OSVR_ClientContext, OSVR_ClientInterface]
    mylib.osvrClientFreeInterface.restype = OSVR_ReturnCode
	return mylib.osvrClientFreeInterface(ctx, iface)

def osvrClientGetStringParameterLength(ctx, path, len):
    mylib.osvrClientGetStringParameterLength.argtypes = [OSVR_ClientContext, c_char_p, c_size_t]
    mylib.osvrClientGetStringParameterLength.restype = OSVR_ReturnCode
	return mylib.osvrGetStringParameterLength(ctx, c_char_p(path), c_size_t(len)

def osvrClientGetStringParameter(ctx, path, buf, len):
    mylib.osvrClientGetStringParameterLength.argtypes = [OSVR_ClientContext, c_char_p, c_char_p c_size_t]
    mylib.osvrClientGetStringParameterLength.restype = OSVR_ReturnCode
	return mylib.osvrClientGetStringParameter(ctx, c_char_p(path), c_char_p(buf), c_size_t(len);

def osvrClientGetDisplay(ctx, disp):
    mylib.osvrClientGetDisplay.argtypes = [OSVR_ClientContext, pointer(OSVR_DisplayConfig)]
    mylib.osvrClientGetDisplay.restype = OSVR_ReturnCode
    return mylib.osvrClientGetDisplay(ctx, disp)

def osvrClientFreeDisplay(disp):
    mylib.osvrClientFreeDisplay.argtypes = [OSVR_DisplayConfig]
    mylib.osvrClientFreeDisplay.restype = OSVR_ReturnCode
    return mylib.osvrClientFreeDisplay(disp)

def osvrClientCheckDisplayStartup(disp):
    mylib.osvrClientCheckDisplayStartup.argtypes = [OSVR_DisplayConfig]
    mylib.osvrClientCheckDisplayStartup.restype = OSVR_ReturnCode
    return mylib.osvrClientCheckDisplayStartup(disp)

def osvrClientGetNumDisplayInputs(disp, numDisplayInputs):
    mylib.osvrClientGetNumDisplayInputs.argtypes = [OSVR_DisplayConfig, pointer(OSVR_DisplayInputCount)]
    mylib.osvrClientGetNumDisplayInputs.restype = OSVR_ReturnCode
    return mylib.osvrClientGetNumDisplayInputs(disp, numDisplayInputs)

def osvrClientGetDisplayDimensions(disp, displayInputIndex, width, height):
    mylib.osvrClientGetDisplayDimensions.argtypes = [OSVR_DisplayConfig, OSVR_DisplayInputCount, pointer(OSVR_DisplayDimension), pointer(OSVR_DisplayDimension)]
    mylib.osvrClientGetDisplayDimensions.restype = OSVR_ReturnCode
    return mylib.osvrClientGetDisplayDimensions(disp, displayInputIndex, width, height)

def osvrClientGetNumViewers(disp, viewers):
    mylib.osvrClientGetNumViewers.argtypes = [OSVR_DisplayConfig, pointer(OSVR_ViewerCount)]
    mylib.osvrClientGetNumViewers.restype = OSVR_ReturnCode
    return mylib.osvrClientGetNumViewers(disp, viewers)

def osvrClientGetViewerPose(disp, viewer, pose):
    mylib.osvrClientGetViewerPose.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, pointer(OSVR_Pose3)]
    mylib.osvrClientGetViewerPose.restype = OSVR_ReturnCode
    return mylib.osvrClientGetViewerPose(disp, viewer, pose)

def osvrClientGetNumEyesForViewer(disp, viewer, eyes):
    mylib.osvrClientGetNumEyesForViewer.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, pointer(OSVR_EyeCount)]
    mylib.osvrClientGetNumEyesForViewer.restype = OSVR_ReturnCode
    return mylib.osvrClientGetNumEyesForViewer(disp, viewer, eyes)

def osvrClientGetViewerEyePose(disp, viewer, eye, pose):
    mylib.osvrClientGetViewerEyePose.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, OSVR_EyeCount, pointer(OSVR_Pose3)]
    mylib.osvrClientGetViewerEyePose.restype = OSVR_ReturnCode
    return mylib.osvrClientGetViewerPose(disp, viewer, eye, pose)

def osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, mat):
    mylib.osvrClientGetViewerEyeViewMatrixd.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, OSVR_EyeCount, OSVR_MatrixConventions, pointer(c_double)]
    mylib.osvrClientGetViewerEyeViewMatrixd.restype = OSVR_ReturnCode
    return mylib.osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, pointer(c_double(mat)))

def osvrClientGetViewerEyeViewMatrixf(disp, viewer, eye, flags, mat):
    mylib.osvrClientGetViewerEyeViewMatrixf.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, OSVR_EyeCount, OSVR_MatrixConventions, pointer(c_float)]
    mylib.osvrClientGetViewerEyeViewMatrixf.restype = OSVR_ReturnCode
    return mylib.osvrClientGetViewerEyeViewMatrixd(disp, viewer, eye, flags, pointer(c_float(mat)))

def osvrClientGetNumSurfacesForViewerEye(disp, viewer, eye, surfaces):
    mylib.osvrClientGetNumSurfacesForViewerEye.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, OSVR_EyeCount, pointer(OSVR_SurfaceCount)]
    mylib.osvrClientGetNumSurfacesForViewerEye.restype = OSVR_ReturnCode
    return mylib.osvrClientGetNumSurfacesForViewerEye(disp, viewer, eye, surfaces)

def osvrClientGetRelativeViewportForViewerEyeSurface(disp, viewer, eye, surface, left, bottom, width, height):
    mylib.osvrClientGetRelativeViewportForViewerEyeSurface.argtypes = [OSVR_DisplayConfig, OSVR_ViewerCount, OSVR_EyeCount, OSVR_SurfaceCount, pointer(OSVR_ViewportDimension), pointer(OSVR_ViewportDimension), pointer(OSVR_ViewportDimension), pointer(OSVR_ViewportDimension)]
    mylib.osvrClientGetRelativeViewportForViewerEyeSurface.restype = OSVR_ReturnCode
    return mylib.osvrClientGetRelativeViewportForViewerEyeSurface(disp, viewer, eye, surface, left, bottom, width, height)

def osvrClientGetViewerEyeSurfaceDisplayInputIndex(disp, viewer, eye, surface, displayInput):
    return osvrClientGetViewerEyeSurfaceDisplayInputIndex(disp, viewer, eye, surface, displayInput)

def osvrClientGetViewerEyeSurfaceProjectionMatrixd(disp, viewer, eye, surface, near, far, flags, matrix):
    return mylib.osvrClientGetViewerEyeSurfaceProjectionMatrixd(disp, viewer, eye, surface, near, far, flags, matrix)

def osvrClientGetViewerEyeSurfaceProjectionMatrixf(disp, viewer, eye, surface, near, far, flags, matrix):
    return mylib.osvrClientGetViewerEyeSurfaceProjectionMatrixf(disp, viewer, eye, surface, near, far, flags, matrix)

def osvrClientGetViewerEyeSurfaceProjectionClippingPlanes(disp, viewer, eye, surface, left, right, bottom, top):
    return mylib.osvrClientGetViewerEyeSurfaceProjectionClippingPlanes(disp, viewer, eye, surface, left, right, bottom, top)

def osvrClientDoesViewerEyeSurfaceWantDistortion(disp, viewer, eye, surface, distortionRequested):
    return mylib.osvrClientDoesViewerEyeSurfaceWantDistortion(disp, viewer, eye, surface, distortionRequested)

def osvrClientGetViewerEyeSurfaceRadialDistortionPriority(disp, viewer, eye, surface, priority):
    return mylib.osvrClientGetViewerEyeSurfaceRadialDistortionPriority(disp, viewer, eye, surface, priority)

def osvrClientGetViewerEyeSurfaceRadialDistortion(disp, viewer, eye, surface, params):
    return mylib.osvrClientGetViewerEyeSurfaceRadialDistortion(disp, viewer, eye, surface, params)<|endoftext|>