<commit_before>from .core import StructuredNode, cypher_query, connection
from .relationship_manager import rel_helper
import inspect

OPERATOR_TABLE = {
    'lt': '<',
    'gt': '>',
    'lte': '<=',
    'gte': '>=',
    'ne': '<>',
}

def install_traversals(cls, node_set):
    """
    from a StructuredNode class install Traversal objects for each
    relationship definition on a NodeSet instance
    """
    rels = cls.defined_properties(rels=True, aliases=False, properties=False)

    for key, value in rels.items():
        if hasattr(node_set, key):
            raise ValueError("Can't install traversal '{}' exists on NodeSet".format(key))

        traversal = Traversal(
            source=node_set,
            key=key,
            definition=getattr(cls, key).definition)

        setattr(node_set, key, traversal)

def process_filter_args(cls, kwargs):
    """
    loop through properties in filter parameters check they match class definition
    deflate them and convert into something easy to generate cypher from
    """

    output = {}

    for key, value in kwargs.items():
        if '__' in key:
            prop, operator = key.split('__')
            operator = OPERATOR_TABLE[operator]
        else:
            prop = key
            operator = '='

        if not prop in cls.defined_properties(rels=False, aliases=False):
            raise ValueError("No such property {} on {}".format(prop, cls.__name__))

        deflated_value = getattr(cls, prop).deflate(value)
        output[prop] = (operator, deflated_value)

    return output

def process_has_args(cls, kwargs):
    """
    loop through has parameters check they correspond to class rels defined
    """
    rel_definitions = cls.defined_properties(properties=False, rels=True, aliases=False)

    match, dont_match = {}, {}

    for key, value in kwargs.items():
        if not key in rel_definitions:
            raise ValueError("No such relation {} defined on a {}".format(key, cls.__name__))

        rhs_ident = key

        rel_definitions[key].build_manager(None, key) # produces label_map in definition

        if value is True:
            match[rhs_ident] = rel_definitions[key].definition
        elif value is False:
            dont_match[rhs_ident] = rel_definitions[key].definition
        elif isinstance(value, NodeSet):
            raise NotImplementedError("Not implemented yet")
        else:
            raise ValueError("Expecting True / False / NodeSet got: " + repr(value))

    return match, dont_match

class NodeSet(object):
    """
    a set of matched nodes of a single type
        source: how to produce the set of nodes
        node_cls: what type of nodes are they
    """
    def __init__(self, source):
        self.source = source  # could be a Traverse object or a node class
        if isinstance(source, Traversal):
            self.source_class = source.target_class
        elif inspect.isclass(source) and issubclass(source, StructuredNode):
            self.source_class = source
        elif isinstance(source, StructuredNode):
            self.source_class = source.__class__
        else:
            raise ValueError("Bad source for nodeset " + repr(source))

        # setup Traversal objects using relationship definitions
        install_traversals(self.source_class, self)

        self.filters = []

        # used by has()
        self.must_match = {}
        self.dont_match = {}

    def __get__(self, instance, type=None):
        if instance is not None:
            raise AttributeError("NodeSet isn't accessible via %s instances" % type.__name__)
        return self

    def filter(self, **kwargs):
        output = process_filter_args(self.source_class, kwargs)
        self.filters.append(output)
        return self

    def exclude(self, **kwargs):
        output = process_filter_args(self.source_class, kwargs)
        self.filters.append({'__NOT__': output})
        return self

    def has(self, **kwargs):
        must_match, dont_match = process_has_args(self.source_class, kwargs)
        self.must_match.update(must_match)
        self.dont_match.update(dont_match)
        return self

class Traversal(object):
    """
        source: start of traversal could be any of: StructuredNode instance, StucturedNode class, NodeSet
        definition: relationship definition
    """
    def __init__(self, source, key, definition):
        self.source = source

        if isinstance(source, Traversal):
            self.source_class = source.target_class
        elif inspect.isclass(source) and issubclass(source, StructuredNode):
            self.source_class = source
        elif isinstance(source, StructuredNode):
            self.source_class = source.__class__
        elif isinstance(source, NodeSet):
            self.source_class = source.source_class
        else:
            raise ValueError("Bad source for traversal: {}".format(repr(source)))

        self.definition = definition
        self.target_class = definition['label_map'].values()[0]
        self.name = key
        self.filters = []

    def match(self, **kwargs):
        if not 'model' in self.definition:
            raise ValueError("match() only available on relationships with a model")
        if kwargs:
            self.filters.append(process_filter_args(self.definition['model'], kwargs))
        return self

class QueryBuilder(object):
    def __init__(self, node_set):
        self.node_set = node_set
        self._ast = {'match': [], 'where': []}
        self._query_params = {}
        self._place_holder_registry = {}
        self._ident_count = 0

    def build_ast(self):
        self.build_source(self.node_set)

    def build_source(self, source):
        if isinstance(source, Traversal):
            return self.build_traversal(source)
        elif isinstance(source, NodeSet):
            if inspect.isclass(source.source) and issubclass(source.source, StructuredNode):
                ident = self.build_label(source.source.__label__.lower(), source.source)
            else:
                ident = self.build_source(source.source)

            self.build_additional_match(ident, source)

            if source.filters:
                self.build_where_stmt(ident, source.filters)

            return ident
        elif isinstance(source, StructuredNode):
            return self.build_node(source)
        else:
            raise ValueError("Unknown source type " + repr(source))

    def create_ident(self):
        self._ident_count += 1
        return 'r' + str(self._ident_count)

    def build_traversal(self, traversal):
        """
        traverse a relationship from a node to a set of nodes
        """
        # build source
        lhs_ident = self.build_source(traversal.source) + ':' + traversal.source_class.__label__
        rhs_ident = traversal.name + ':' + traversal.target_class.__label__
        self._ast['return'] = traversal.name
        self._ast['result_class'] = traversal.target_class

        rel_ident = self.create_ident()
        stmt = rel_helper(lhs=lhs_ident, rhs=rhs_ident, ident=rel_ident, **traversal.definition)
        self._ast['match'].append(stmt)

        if traversal.filters:
            self.build_where_stmt(rel_ident, traversal.filters)

        return rhs_ident

    def build_node(self, node):
        # TODO make node id a parameter
        ident = node.__class__.__name__.lower()
        if not 'start' in self._ast:
            self._ast['start'] = []
        self._ast['start'].append('{} = node({})'.format(ident, node._id))
        self._ast['return'] = ident
        self._ast['result_class'] = node.__class__
        return ident

    def build_label(self, ident, cls):
        """
        match nodes by a label
        """
        ident_w_label = ident + ':' + cls.__label__
        self._ast['match'].append('({})'.format(ident_w_label))
        self._ast['return'] = ident
        self._ast['result_class'] = cls
        return ident

    def build_additional_match(self, ident, node_set):
        """
            handle additional matches supplied by 'has()' calls
        """
        # TODO add support for labels
        source_ident = ident

        for key, value in node_set.must_match.items():
            label = ':' + value['label_map'].keys()[0]
            if isinstance(value, dict):
                stmt = rel_helper(lhs=source_ident, rhs=label, ident='', **value)
                self._ast['where'].append(stmt)
            elif isinstance(value, tuple):
                rel_manager, ns = value
                self.add_node_set(ns, key)

        for key, val in node_set.dont_match.items():
            label = ':' + val['label_map'].keys()[0]
            if isinstance(val, dict):
                stmt = rel_helper(lhs=source_ident, rhs=label, ident='', **val)
                self._ast['where'].append('NOT ' + stmt)
            else:
                raise ValueError("WTF? " + repr(val))

    def _register_place_holder(self, key):
        if key in self._place_holder_registry:
            self._place_holder_registry[key] += 1
        else:
            self._place_holder_registry[key] = 1
        return key + '_' + str(self._place_holder_registry[key])

    def build_where_stmt(self, ident, filters):
        """
        construct a where statement
        """
        stmts = []
        for row in filters:
            negate = False

            # pre-process NOT cases as they are nested dicts
            if '__NOT__' in row and len(row) == 1:
                negate = True
                row = row['__NOT__']

            for prop, op_and_val in row.items():
                op, val = op_and_val
                place_holder = self._register_place_holder(ident + '_' + prop)
                statement = '{} {}.{} {} {{{}}}'.format(
                    'NOT' if negate else '', ident, prop, op, place_holder)
                stmts.append(statement)
                self._query_params[place_holder] = val

        self._ast['where'].append(' AND '.join(stmts))

    def build_query(self):
        query = ''

        if 'start' in self._ast:
            query += 'START '
            query += ', '.join(self._ast['start'])

        query += ' MATCH '
        query += ', '.join(self._ast['match'])

        if 'where' in self._ast and self._ast['where']:
            query += ' WHERE '
            query += ', '.join(self._ast['where'])

        query += ' RETURN ' + self._ast['return']
        return query

    def execute(self):
        self.build_ast()
        query = self.build_query()
        results, _ = cypher_query(connection(), query, self._query_params)
        if results:
            return [self._ast['result_class'].inflate(n) for n in results[0]]
        return []
<commit_msg>Unused<commit_after>from .core import StructuredNode, cypher_query, connection
from .relationship_manager import rel_helper
import inspect

OPERATOR_TABLE = {
    'lt': '<',
    'gt': '>',
    'lte': '<=',
    'gte': '>=',
    'ne': '<>',
}

def install_traversals(cls, node_set):
    """
    from a StructuredNode class install Traversal objects for each
    relationship definition on a NodeSet instance
    """
    rels = cls.defined_properties(rels=True, aliases=False, properties=False)

    for key, value in rels.items():
        if hasattr(node_set, key):
            raise ValueError("Can't install traversal '{}' exists on NodeSet".format(key))

        traversal = Traversal(
            source=node_set,
            key=key,
            definition=getattr(cls, key).definition)

        setattr(node_set, key, traversal)

def process_filter_args(cls, kwargs):
    """
    loop through properties in filter parameters check they match class definition
    deflate them and convert into something easy to generate cypher from
    """

    output = {}

    for key, value in kwargs.items():
        if '__' in key:
            prop, operator = key.split('__')
            operator = OPERATOR_TABLE[operator]
        else:
            prop = key
            operator = '='

        if not prop in cls.defined_properties(rels=False, aliases=False):
            raise ValueError("No such property {} on {}".format(prop, cls.__name__))

        deflated_value = getattr(cls, prop).deflate(value)
        output[prop] = (operator, deflated_value)

    return output

def process_has_args(cls, kwargs):
    """
    loop through has parameters check they correspond to class rels defined
    """
    rel_definitions = cls.defined_properties(properties=False, rels=True, aliases=False)

    match, dont_match = {}, {}

    for key, value in kwargs.items():
        if not key in rel_definitions:
            raise ValueError("No such relation {} defined on a {}".format(key, cls.__name__))

        rhs_ident = key

        rel_definitions[key].build_manager(None, key) # produces label_map in definition

        if value is True:
            match[rhs_ident] = rel_definitions[key].definition
        elif value is False:
            dont_match[rhs_ident] = rel_definitions[key].definition
        elif isinstance(value, NodeSet):
            raise NotImplementedError("Not implemented yet")
        else:
            raise ValueError("Expecting True / False / NodeSet got: " + repr(value))

    return match, dont_match

class NodeSet(object):
    """
    a set of matched nodes of a single type
        source: how to produce the set of nodes
        node_cls: what type of nodes are they
    """
    def __init__(self, source):
        self.source = source  # could be a Traverse object or a node class
        if isinstance(source, Traversal):
            self.source_class = source.target_class
        elif inspect.isclass(source) and issubclass(source, StructuredNode):
            self.source_class = source
        elif isinstance(source, StructuredNode):
            self.source_class = source.__class__
        else:
            raise ValueError("Bad source for nodeset " + repr(source))

        # setup Traversal objects using relationship definitions
        install_traversals(self.source_class, self)

        self.filters = []

        # used by has()
        self.must_match = {}
        self.dont_match = {}

    def filter(self, **kwargs):
        output = process_filter_args(self.source_class, kwargs)
        self.filters.append(output)
        return self

    def exclude(self, **kwargs):
        output = process_filter_args(self.source_class, kwargs)
        self.filters.append({'__NOT__': output})
        return self

    def has(self, **kwargs):
        must_match, dont_match = process_has_args(self.source_class, kwargs)
        self.must_match.update(must_match)
        self.dont_match.update(dont_match)
        return self

class Traversal(object):
    """
        source: start of traversal could be any of: StructuredNode instance, StucturedNode class, NodeSet
        definition: relationship definition
    """
    def __init__(self, source, key, definition):
        self.source = source

        if isinstance(source, Traversal):
            self.source_class = source.target_class
        elif inspect.isclass(source) and issubclass(source, StructuredNode):
            self.source_class = source
        elif isinstance(source, StructuredNode):
            self.source_class = source.__class__
        elif isinstance(source, NodeSet):
            self.source_class = source.source_class
        else:
            raise ValueError("Bad source for traversal: {}".format(repr(source)))

        self.definition = definition
        self.target_class = definition['label_map'].values()[0]
        self.name = key
        self.filters = []

    def match(self, **kwargs):
        if not 'model' in self.definition:
            raise ValueError("match() only available on relationships with a model")
        if kwargs:
            self.filters.append(process_filter_args(self.definition['model'], kwargs))
        return self

class QueryBuilder(object):
    def __init__(self, node_set):
        self.node_set = node_set
        self._ast = {'match': [], 'where': []}
        self._query_params = {}
        self._place_holder_registry = {}
        self._ident_count = 0

    def build_ast(self):
        self.build_source(self.node_set)

    def build_source(self, source):
        if isinstance(source, Traversal):
            return self.build_traversal(source)
        elif isinstance(source, NodeSet):
            if inspect.isclass(source.source) and issubclass(source.source, StructuredNode):
                ident = self.build_label(source.source.__label__.lower(), source.source)
            else:
                ident = self.build_source(source.source)

            self.build_additional_match(ident, source)

            if source.filters:
                self.build_where_stmt(ident, source.filters)

            return ident
        elif isinstance(source, StructuredNode):
            return self.build_node(source)
        else:
            raise ValueError("Unknown source type " + repr(source))

    def create_ident(self):
        self._ident_count += 1
        return 'r' + str(self._ident_count)

    def build_traversal(self, traversal):
        """
        traverse a relationship from a node to a set of nodes
        """
        # build source
        lhs_ident = self.build_source(traversal.source) + ':' + traversal.source_class.__label__
        rhs_ident = traversal.name + ':' + traversal.target_class.__label__
        self._ast['return'] = traversal.name
        self._ast['result_class'] = traversal.target_class

        rel_ident = self.create_ident()
        stmt = rel_helper(lhs=lhs_ident, rhs=rhs_ident, ident=rel_ident, **traversal.definition)
        self._ast['match'].append(stmt)

        if traversal.filters:
            self.build_where_stmt(rel_ident, traversal.filters)

        return rhs_ident

    def build_node(self, node):
        # TODO make node id a parameter
        ident = node.__class__.__name__.lower()
        if not 'start' in self._ast:
            self._ast['start'] = []
        self._ast['start'].append('{} = node({})'.format(ident, node._id))
        self._ast['return'] = ident
        self._ast['result_class'] = node.__class__
        return ident

    def build_label(self, ident, cls):
        """
        match nodes by a label
        """
        ident_w_label = ident + ':' + cls.__label__
        self._ast['match'].append('({})'.format(ident_w_label))
        self._ast['return'] = ident
        self._ast['result_class'] = cls
        return ident

    def build_additional_match(self, ident, node_set):
        """
            handle additional matches supplied by 'has()' calls
        """
        # TODO add support for labels
        source_ident = ident

        for key, value in node_set.must_match.items():
            label = ':' + value['label_map'].keys()[0]
            if isinstance(value, dict):
                stmt = rel_helper(lhs=source_ident, rhs=label, ident='', **value)
                self._ast['where'].append(stmt)
            elif isinstance(value, tuple):
                rel_manager, ns = value
                self.add_node_set(ns, key)

        for key, val in node_set.dont_match.items():
            label = ':' + val['label_map'].keys()[0]
            if isinstance(val, dict):
                stmt = rel_helper(lhs=source_ident, rhs=label, ident='', **val)
                self._ast['where'].append('NOT ' + stmt)
            else:
                raise ValueError("WTF? " + repr(val))

    def _register_place_holder(self, key):
        if key in self._place_holder_registry:
            self._place_holder_registry[key] += 1
        else:
            self._place_holder_registry[key] = 1
        return key + '_' + str(self._place_holder_registry[key])

    def build_where_stmt(self, ident, filters):
        """
        construct a where statement
        """
        stmts = []
        for row in filters:
            negate = False

            # pre-process NOT cases as they are nested dicts
            if '__NOT__' in row and len(row) == 1:
                negate = True
                row = row['__NOT__']

            for prop, op_and_val in row.items():
                op, val = op_and_val
                place_holder = self._register_place_holder(ident + '_' + prop)
                statement = '{} {}.{} {} {{{}}}'.format(
                    'NOT' if negate else '', ident, prop, op, place_holder)
                stmts.append(statement)
                self._query_params[place_holder] = val

        self._ast['where'].append(' AND '.join(stmts))

    def build_query(self):
        query = ''

        if 'start' in self._ast:
            query += 'START '
            query += ', '.join(self._ast['start'])

        query += ' MATCH '
        query += ', '.join(self._ast['match'])

        if 'where' in self._ast and self._ast['where']:
            query += ' WHERE '
            query += ', '.join(self._ast['where'])

        query += ' RETURN ' + self._ast['return']
        return query

    def execute(self):
        self.build_ast()
        query = self.build_query()
        results, _ = cypher_query(connection(), query, self._query_params)
        if results:
            return [self._ast['result_class'].inflate(n) for n in results[0]]
        return []
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Defines the nepdate class
"""

import sys
from datetime import date, timedelta
from . import values, functions

class nepdate(object):
    """
    Represents nepali date
    """

    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

        self.en_date = None

    def __unicode__(self):
        return u"Bikram Sambat Date (%d:%d:%d)" % (self.year, self.month, self.day)

    def __str__(self):
        return self.__unicode__()

    def __eq__(self, other):
        return self.year == other.year and \
            self.month == other.month and \
            self.day == other.day

    def __gt__(self, other):
        if self.year > other.year:
            return True
        elif self.year < other.year:
            return False
        else:
            if self.month > other.month:
                return True
            elif self.month < other.month:
                return False
            else:
                if self.day > other.day:
                    return True
                return False

    def __ge__(self, other):
        return self == other or self > other

    def __lt__(self, other):
        return (not self == other) and (not self > other)

    def __le__(self, other):
        return not self > other

    def __add__(self, other):
        """
        Add operator for timedelta
        """
        year = self.year
        month = self.month
        day = self.day

        days_remain = other.days

        if days_remain == 0:
            return self
        elif days_remain < 0:
            return self - (other * -1)

        while True:
            # Make sure we're still in range
            if year > values.END_NP_YEAR:
                raise ValueError("Out of range")
            # The current day + days in timedelta fits in within the current
            # month
            if days_remain + day <= values.NEPALI_MONTH_DAY_DATA[year][month - 1]:
                day = day + days_remain
                return nepdate(year, month, day).update()
            else:
                days_remain -= values.NEPALI_MONTH_DAY_DATA[
                    year][month - 1] - day + 1
                day = 1
                month += 1
                if month > 12:
                    month = 1
                    year += 1

    def __sub__(self, other):
        """
        Subtraction operator.
        Returns a timedelta object
        """
        if isinstance(other, timedelta):
            # Subtract number of days from the date
            days_remain = other.days
            if days_remain == 0:
                return self
            elif days_remain < 0:
                return self + (-1 * other)
            # Subtract the number of days
            year = self.year
            month = self.month
            day = self.day
            while True:
                if year < values.START_NP_YEAR:
                    raise ValueError("Out of range")
                if days_remain < day:
                    day = day - days_remain
                    return nepdate(year, month, day).update()
                days_remain -= day
                month = month - 1
                if month < 1:
                    month = 12
                    year = year - 1
                day = values.NEPALI_MONTH_DAY_DATA[year][month - 1]

        greater = self
        smaller = other
        multiplier = 1
        if self < other:
            greater = other
            smaller = self
            multiplier = -1

        # Delta in days
        num_days = 0
        if greater.year > smaller.year:
            # First of all, get the days remaining in the smaller year
            # till year end
            smaller_days_remain = nepdate(
                smaller.year, 12, values.NEPALI_MONTH_DAY_DATA[
                    smaller.year][12 - 1]
            ) - smaller

            year_remain = range(smaller.year + 1, greater.year)
            for year in year_remain:
                num_days += sum(values.NEPALI_MONTH_DAY_DATA[year])

            # Find the days past in the greater year since january
            greater_days_remain = greater - \
                nepdate(greater.year, 1, 1) + timedelta(1)

            total_days = timedelta(days=num_days) + \
                greater_days_remain + \
                smaller_days_remain

            return multiplier * total_days

        # Same year
        if greater.month > smaller.month:
            smaller_days_remain = nepdate(
                smaller.year,
                smaller.month,
                values.NEPALI_MONTH_DAY_DATA[smaller.year][smaller.month - 1]
            ) - smaller

            month_remain = range(smaller.month + 1, greater.month)
            for month in month_remain:
                num_days += values.NEPALI_MONTH_DAY_DATA[
                    smaller.year][month - 1]

            greater_days_remain = greater - nepdate(
                greater.year, greater.month, 1) + timedelta(days=1)
            # One is added to adjust for 1 gate. For example, if we're counting from
            # biasakh 12 to jestha 18, it will count from baisakh 12 to baisakh 30
            # Then again, from jeth 1 to jeth 18. In this process, jeth 1 is neglected
            # Hence, 1 is added here

            total_days = timedelta(days=num_days) + \
                greater_days_remain + \
                smaller_days_remain

            return multiplier * total_days

        # Same year and same month but different days
        total_days = timedelta(days=greater.day - smaller.day)
        return total_days

    @classmethod
    def from_ad_date(cls, date):
        """
        Gets a nepdate object from gregorian calendar date
        """
        functions.check_valid_ad_range(date)
        days = values.START_EN_DATE - date

        # Add the required number of days to the start nepali date
        start_date = nepdate(values.START_NP_YEAR, 1, 1)
        return start_date + (date - values.START_EN_DATE)

    @classmethod
    def from_bs_date(cls, year, month, day):
        """
        Create and update an nepdate object for bikram sambat date
        """
        return nepdate(year, month, day).update()

    @classmethod
    def today(today):
        """
        Returns today's date in nepali calendar
        """
        return nepdate.from_ad_date(date.today())

    @classmethod
    def fromtimestamp(cls, timestamp):
        """
        Returns a nepdate object created from timestamp
        """
        return nepdate.from_ad_date(date.fromtimestamp(timestamp))

    def weekday(self):
        """
        Returns weekday for the date.
        0 : Aaitabar
        6 : Sanibar
        """
        return (self.en_date.weekday() + 1) % 7

    def en_weekday(self):
        """
        Returns weekday with each week starting in monday
        monday = 0
        sunday = 7
        """
        return self.en_date.weekday()

    def update(self):
        """
        Updates information about the nepdate
        """
        # Here's a trick to find the gregorian date:
        # We find the number of days from earliest nepali date to the current
        # day. We then add the number of days to the earliest english date
        self.en_date = values.START_EN_DATE + \
            (
                self - nepdate(
                    values.START_NP_YEAR,
                    1,
                    1
                )
            )
        return self
<commit_msg>Update docstrings for some functions<commit_after># -*- coding: utf-8 -*-
"""
Defines the nepdate class
"""

import sys
from datetime import date, timedelta
from . import values, functions

class nepdate(object):
    """ Nepali Date class that implements a single nepali date
    """

    def __init__(self, year, month, day):
        """ Initializer for nepdate
        Params:
            year : Year of the date
            month : Month of the date
            day : Day of the date
        English date is not updated in constructor. 'update' should
        be called explicitly"""
        self.year = year
        self.month = month
        self.day = day

        self.en_date = None

    def __unicode__(self):
        return u"Bikram Sambat Date (%d:%d:%d)" % (self.year, self.month, self.day)

    def __str__(self):
        return self.__unicode__()

    def __eq__(self, other):
        return self.year == other.year and \
            self.month == other.month and \
            self.day == other.day

    def __gt__(self, other):
        if self.year > other.year:
            return True
        elif self.year < other.year:
            return False
        else:
            if self.month > other.month:
                return True
            elif self.month < other.month:
                return False
            else:
                if self.day > other.day:
                    return True
                return False

    def __ge__(self, other):
        return self == other or self > other

    def __lt__(self, other):
        return (not self == other) and (not self > other)

    def __le__(self, other):
        return not self > other

    def __add__(self, other):
        """Adds nepdate with timedelta object"""
        year = self.year
        month = self.month
        day = self.day

        days_remain = other.days

        if days_remain == 0:
            return self
        elif days_remain < 0:
            return self - (other * -1)

        while True:
            # Make sure we're still in range
            if year > values.END_NP_YEAR:
                raise ValueError("Out of range")
            # The current day + days in timedelta fits in within the current
            # month
            if days_remain + day <= values.NEPALI_MONTH_DAY_DATA[year][month - 1]:
                day = day + days_remain
                return nepdate(year, month, day).update()
            else:
                days_remain -= values.NEPALI_MONTH_DAY_DATA[
                    year][month - 1] - day + 1
                day = 1
                month += 1
                if month > 12:
                    month = 1
                    year += 1

    def __sub__(self, other):
        """Subtraction for nepdate. Subtraction can be done with either
        timedelta object to obtain nepdate object or with nepdate object
        to find timedelta object (number of days between the two dates)
        """
        if isinstance(other, timedelta):
            # Subtract number of days from the date
            days_remain = other.days
            if days_remain == 0:
                return self
            elif days_remain < 0:
                return self + (-1 * other)
            # Subtract the number of days
            year = self.year
            month = self.month
            day = self.day
            while True:
                if year < values.START_NP_YEAR:
                    raise ValueError("Out of range")
                if days_remain < day:
                    day = day - days_remain
                    return nepdate(year, month, day).update()
                days_remain -= day
                month = month - 1
                if month < 1:
                    month = 12
                    year = year - 1
                day = values.NEPALI_MONTH_DAY_DATA[year][month - 1]

        greater = self
        smaller = other
        multiplier = 1
        if self < other:
            greater = other
            smaller = self
            multiplier = -1

        # Delta in days
        num_days = 0
        if greater.year > smaller.year:
            # First of all, get the days remaining in the smaller year
            # till year end
            smaller_days_remain = nepdate(
                smaller.year, 12, values.NEPALI_MONTH_DAY_DATA[
                    smaller.year][12 - 1]
            ) - smaller

            year_remain = range(smaller.year + 1, greater.year)
            for year in year_remain:
                num_days += sum(values.NEPALI_MONTH_DAY_DATA[year])

            # Find the days past in the greater year since january
            greater_days_remain = greater - \
                nepdate(greater.year, 1, 1) + timedelta(1)

            total_days = timedelta(days=num_days) + \
                greater_days_remain + \
                smaller_days_remain

            return multiplier * total_days

        # Same year
        if greater.month > smaller.month:
            smaller_days_remain = nepdate(
                smaller.year,
                smaller.month,
                values.NEPALI_MONTH_DAY_DATA[smaller.year][smaller.month - 1]
            ) - smaller

            month_remain = range(smaller.month + 1, greater.month)
            for month in month_remain:
                num_days += values.NEPALI_MONTH_DAY_DATA[
                    smaller.year][month - 1]

            greater_days_remain = greater - nepdate(
                greater.year, greater.month, 1) + timedelta(days=1)
            # One is added to adjust for 1 gate. For example, if we're counting from
            # biasakh 12 to jestha 18, it will count from baisakh 12 to baisakh 30
            # Then again, from jeth 1 to jeth 18. In this process, jeth 1 is neglected
            # Hence, 1 is added here

            total_days = timedelta(days=num_days) + \
                greater_days_remain + \
                smaller_days_remain

            return multiplier * total_days

        # Same year and same month but different days
        total_days = timedelta(days=greater.day - smaller.day)
        return total_days

    @classmethod
    def from_ad_date(cls, date):
        """ Gets a nepdate object from gregorian calendar date """
        functions.check_valid_ad_range(date)
        days = values.START_EN_DATE - date

        # Add the required number of days to the start nepali date
        start_date = nepdate(values.START_NP_YEAR, 1, 1)
        return start_date + (date - values.START_EN_DATE)

    @classmethod
    def from_bs_date(cls, year, month, day):
        """ Create and update an nepdate object for bikram sambat date """
        return nepdate(year, month, day).update()

    @classmethod
    def today(today):
        """ Returns today's date in nepali calendar """
        return nepdate.from_ad_date(date.today())

    @classmethod
    def fromtimestamp(cls, timestamp):
        """ Returns a nepdate object created from timestamp """
        return nepdate.from_ad_date(date.fromtimestamp(timestamp))

    def weekday(self):
        """ Returns weekday for the date.
        0 : Aaitabar
        6 : Sanibar """
        return (self.en_date.weekday() + 1) % 7

    def en_weekday(self):
        """ Returns weekday with each week starting in monday
        monday = 0
        sunday = 7 """
        return self.en_date.weekday()

    def update(self):
        """ Updates information about the nepdate """
        # Here's a trick to find the gregorian date:
        # We find the number of days from earliest nepali date to the current
        # day. We then add the number of days to the earliest english date
        self.en_date = values.START_EN_DATE + \
            (
                self - nepdate(
                    values.START_NP_YEAR,
                    1,
                    1
                )
            )
        return self
<|endoftext|>


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

import os, sys
import yaml
import pyme.core
import pyme.constants.sigsum
import Tix
#import servent # we'll do that later
from datamanager import *

authority = "8F5630AB" #read from config file
directory = "./data" #make this path absolute; read from config file

#where do we put this one and all the rest of the crypto context?
def desigsum(sigsum):
  str = ""
  #for constant in dir(pyme.constants.sigsum):
  if (sigsum & pyme.constants.sigsum.VALID)      : str += "VALID;"
  if (sigsum & pyme.constants.sigsum.GREEN)      : str += "GREEN;"
  if (sigsum & pyme.constants.sigsum.RED)        : str += "RED;"
  if (sigsum & pyme.constants.sigsum.KEY_REVOKED): str += "KEY_REVOKED;"
  if (sigsum & pyme.constants.sigsum.KEY_EXPIRED): str += "KEY_EXPIRED;"
  if (sigsum & pyme.constants.sigsum.SIG_EXPIRED): str += "SIG_EXPIRED;"
  if (sigsum & pyme.constants.sigsum.KEY_MISSING): str += "KEY_MISSING;"
  if (sigsum & pyme.constants.sigsum.CRL_MISSING): str += "CRL_MISSING;"
  if (sigsum & pyme.constants.sigsum.CRL_TOO_OLD): str += "CRL_TOO_OLD;"
  if (sigsum & pyme.constants.sigsum.BAD_POLICY) : str += "BAD_POLICY;"
  if (sigsum & pyme.constants.sigsum.SYS_ERROR)  : str += "SYS_ERROR;"
  return str

class Peergov:

  def loadTopic(self, xdir):
    topicsig = xdir + "/" + ".topic.yaml"
    if os.path.exists(topicsig):
      try:
        yamldata = open(topicsig, "r")
        data = yaml.load(yamldata.read())
        if data:
          sig   = pyme.core.Data(data['sig'])
          topicy = pyme.core.Data()
          if not self.cctx.op_verify(sig, None, topicy):
            sigs = self.cctx.op_verify_result().signatures
            sig = sigs[0] # we don't support multiple.
            valid = (sig.summary & pyme.constants.sigsum.VALID) > 0
            if valid:
              #TODO: get signature key and name using get_key(fpr)
              sigkey = self.cctx.get_key(sig.fpr, 0)
              topicy.seek(0,0)
              topic = yaml.load(topicy.read())
              auth = self.manager.getAuthority(sig.fpr)
              auth.name = sigkey.uids[0].uid
              to = auth.topics[xdir]=Topic()
              to.data      = topic
              to.signature = data['sig']
            else:
              print ("Signature of %s is not VALID - %s." % (str(xdir), desigsum(sig.summary)))
          else:
            print ("Verification of topic %s failed." % str(xdir))
      except Exception,e:
        print("Failed to parse topic signature. %s" % str(e))
    else:
      print("No topic signature found for %s." % str(xdir))
      pass

  def loadData(self, dir, file): #proposals and votes?
    if file==".topic.yaml":
      return
    #if dir in self.topics:
    #  try:
    #    yamldata = open(dir + "/" + file, "r")
    #    data = yaml.load(yamldata.read())
    #    if data:
    #      #verify signature
    #      self.topics[dir][file]=data
    #  except (Exception,e):
    #    print("Failed to parse data. %s" % str(e))
    #else:
    #  print("Skipping data file for topic %s. Not authorized." % str(dir))

  def initGui(self):
    self.gui = PeerGui(self.manager)
    self.gui.mainloop()

  def __init__(self):
    self.manager = DataManager()
    self.cctx   = pyme.core.Context() #crypto context

    if not os.path.exists(directory):
      try:
        print("Directory %s not found. Creating." % str(directory))
        os.mkdir(directory)
      except:
        print("Failed creating data directory. Aborting.")
        sys.exit(1)
    if not os.path.isdir(directory):
      print("Path %s is not a directory. Aborting." % str(directory))
      sys.exit(1)

    for root, dirs, files in os.walk(directory):
      for dir in dirs:
        self.loadTopic(root + "/" + dir)
      for file in files:
        self.loadData(root, file)

    self.initGui()

class PeerGui:
  def __init__(self, manager):
    self.manager = manager
    self.frame = Tix.Tk()
    self.wi_topics = Tix.Tree(self.frame)
    self.initTree();
    self.wi_topics.pack()

  def initTree(self):
    for fpr, authority in self.manager.authorities.iteritems():
      self.wi_topics.hlist.add(fpr, itemtype=Tix.IMAGETEXT, text=authority.name,image=self.wi_topics.tk.call('tix', 'getimage', 'folder'))
      for xdir, topic in authority.topics.iteritems():
        self.wi_topics.hlist.add(fpr+xdir, itemtype=Tix.IMAGETEXT, text=topic.data['short'],image=self.wi_topics.tk.call('tix', 'getimage', 'folder'))
        #etc. for proposals, votes, ...
      pass

  def mainloop(self):
    self.frame.mainloop()

Peergov()
#TODO: initiate some servents, once the data has been loaded
<commit_msg>minor update. gui interaction<commit_after># -*- coding: utf-8 -*-

import os, sys
import yaml
import pyme.core
import pyme.constants.sigsum
import Tix
#import servent # we'll do that later
from datamanager import *

authority = "8F5630AB" #read from config file
directory = "./data" #make this path absolute; read from config file

#where do we put this one and all the rest of the crypto context?
def desigsum(sigsum):
  str = ""
  #for constant in dir(pyme.constants.sigsum):
  if (sigsum & pyme.constants.sigsum.VALID)      : str += "VALID;"
  if (sigsum & pyme.constants.sigsum.GREEN)      : str += "GREEN;"
  if (sigsum & pyme.constants.sigsum.RED)        : str += "RED;"
  if (sigsum & pyme.constants.sigsum.KEY_REVOKED): str += "KEY_REVOKED;"
  if (sigsum & pyme.constants.sigsum.KEY_EXPIRED): str += "KEY_EXPIRED;"
  if (sigsum & pyme.constants.sigsum.SIG_EXPIRED): str += "SIG_EXPIRED;"
  if (sigsum & pyme.constants.sigsum.KEY_MISSING): str += "KEY_MISSING;"
  if (sigsum & pyme.constants.sigsum.CRL_MISSING): str += "CRL_MISSING;"
  if (sigsum & pyme.constants.sigsum.CRL_TOO_OLD): str += "CRL_TOO_OLD;"
  if (sigsum & pyme.constants.sigsum.BAD_POLICY) : str += "BAD_POLICY;"
  if (sigsum & pyme.constants.sigsum.SYS_ERROR)  : str += "SYS_ERROR;"
  return str

class Peergov:

  def loadTopic(self, xdir):
    topicsig = xdir + "/" + ".topic.yaml"
    if os.path.exists(topicsig):
      try:
        yamldata = open(topicsig, "r")
        data = yaml.load(yamldata.read())
        if data:
          sig   = pyme.core.Data(data['sig'])
          topicy = pyme.core.Data()
          if not self.cctx.op_verify(sig, None, topicy):
            sigs = self.cctx.op_verify_result().signatures
            sig = sigs[0] # we don't support multiple.
            valid = (sig.summary & pyme.constants.sigsum.VALID) > 0
            if valid:
              #TODO: get signature key and name using get_key(fpr)
              sigkey = self.cctx.get_key(sig.fpr, 0)
              topicy.seek(0,0)
              topic = yaml.load(topicy.read())
              auth = self.manager.getAuthority(sig.fpr)
              auth.name = sigkey.uids[0].uid
              to = auth.topics[xdir]=Topic()
              to.data      = topic
              to.signature = data['sig']
            else:
              print ("Signature of %s is not VALID - %s." % (str(xdir), desigsum(sig.summary)))
          else:
            print ("Verification of topic %s failed." % str(xdir))
      except Exception,e:
        print("Failed to parse topic signature. %s" % str(e))
    else:
      print("No topic signature found for %s." % str(xdir))
      pass

  def loadData(self, dir, file): #proposals and votes?
    if file==".topic.yaml":
      return
    #if dir in self.topics:
    #  try:
    #    yamldata = open(dir + "/" + file, "r")
    #    data = yaml.load(yamldata.read())
    #    if data:
    #      #verify signature
    #      self.topics[dir][file]=data
    #  except (Exception,e):
    #    print("Failed to parse data. %s" % str(e))
    #else:
    #  print("Skipping data file for topic %s. Not authorized." % str(dir))

  def initGui(self):
    self.gui = PeerGui(self.manager)
    self.gui.mainloop()

  def __init__(self):
    self.manager = DataManager()
    self.cctx   = pyme.core.Context() #crypto context

    if not os.path.exists(directory):
      try:
        print("Directory %s not found. Creating." % str(directory))
        os.mkdir(directory)
      except:
        print("Failed creating data directory. Aborting.")
        sys.exit(1)
    if not os.path.isdir(directory):
      print("Path %s is not a directory. Aborting." % str(directory))
      sys.exit(1)

    for root, dirs, files in os.walk(directory):
      for dir in dirs:
        self.loadTopic(root + "/" + dir)
      for file in files:
        self.loadData(root, file)

    self.initGui()

class PeerGui:
  def __init__(self, manager):
    self.manager = manager
    self.frame = Tix.Tk()
    self.wPane = Tix.PanedWindow(self.frame, orientation='horizontal')
    self.wPane1 = self.wPane.add('tree')
    self.wPane2 = self.wPane.add('info')
    self.wTopics = Tix.Tree(self.wPane1)
    self.wTopics['opencmd'] = self.openTree(self.wTopics, None) #lambda dir=None, w=tree: opendir(w, dir)
    self.initTree();
    self.wInfo = Tix.ScrolledText(self.wPane2)
    self.wInfo.text['width']=80
    self.wInfo.text['height']=20
    self.wInfo.text['state'] = 'disabled'
    self.wInfo.pack(expand=1, fill=Tix.BOTH, padx=1, pady=1)
    self.wTopics.pack(expand=1, fill=Tix.BOTH, padx=1, pady=1, side=Tix.LEFT)
    self.wPane.pack(side=Tix.TOP, padx=1, pady=1, fill=Tix.BOTH, expand=1)

  def openTree(self, tree, dir):
    print str((self, tree, dir))

  def initTree(self):
    for fpr, authority in self.manager.authorities.iteritems():
      self.wTopics.hlist.add(fpr, itemtype=Tix.IMAGETEXT, text=authority.name,image=self.wTopics.tk.call('tix', 'getimage', 'folder'))
      for xdir, topic in authority.topics.iteritems():
        self.wTopics.hlist.add(fpr+xdir, itemtype=Tix.IMAGETEXT, text=topic.data['short'],image=self.wTopics.tk.call('tix', 'getimage', 'folder'))
        #etc. for proposals, votes, ...
      pass

  def mainloop(self):
    self.frame.mainloop()

Peergov()
#TODO: initiate some servents, once the data has been loaded
<|endoftext|>


<commit_before># coding: utf-8

from base import BaseTestCase

import utils

from webapp import utils as wutils

class UtilsTestCase(BaseTestCase):

    def test_get_prev_issue(self):
        """
        Teste da função utils.get_prev_issue().

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3]

        prev_issue = wutils.get_prev_issue(issues, issue2)

        self.assertEqual(prev_issue, issue3)

    def test_get_next_issue(self):
        """
        Teste da função utils.get_next_issue().

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3]

        next_issue = wutils.get_next_issue(issues, issue2)

        self.assertEqual(next_issue, issue1)

    def test_get_prev_issue_with_one_item(self):
        """
        Teste da função utils.get_prev_issue() without itens, deve retorna None.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })

        issue = utils.makeOneIssue()

        # criando uma lista de fascículos vazia
        issues = [issue1]

        prev_issue = wutils.get_prev_issue(issues, issue)

        self.assertIsNone(prev_issue)

    def test_get_next_issue_with_one_item(self):
        """
        Teste da função utils.get_next_issue() without itens, deve retorna None.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })

        issue = utils.makeOneIssue()

        # criando uma lista de fascículos vazia
        issues = [issue1]

        next_issue = wutils.get_next_issue(issues, issue)

        self.assertIsNone(next_issue)

    def test_get_prev_issue_when_the_last_issue(self):
        """
        Testando o get_prev_issue quando é acessado um índice inexistente, deve
        retorna None.

        Acessando o a um índice inexistente, o último item da lista irá retornar
        None pois não existe o índice [último] + 1 (Lembrando que a lista de
        fascículo é invertida)

        Portanto a função get_prev_issue soma 1.

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })
        issue4 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '4', 'order': '4', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3, issue4]

        prev_issue = wutils.get_prev_issue(issues, issue4)

        self.assertIsNone(prev_issue)

    def test_get_next_issue_when_first_item(self):
        """
        Testando o get_next_issue quando é acessado o primiero índice, deve
        retorna None.

        Acessando o primiero item da lista irá retornar None.

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })
        issue4 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '4', 'order': '4', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3, issue4]

        next_issue = wutils.get_next_issue(issues, issue1)

        self.assertIsNone(next_issue)
<commit_msg>Adicionando teste unitários para as funções get_prev_article e get_next_article<commit_after># coding: utf-8

from base import BaseTestCase

import utils

from webapp import utils as wutils

class UtilsTestCase(BaseTestCase):

    # Issue
    def test_get_prev_issue(self):
        """
        Teste da função utils.get_prev_issue().

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3]

        prev_issue = wutils.get_prev_issue(issues, issue2)

        self.assertEqual(prev_issue, issue3)

    def test_get_next_issue(self):
        """
        Teste da função utils.get_next_issue().

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3]

        next_issue = wutils.get_next_issue(issues, issue2)

        self.assertEqual(next_issue, issue1)

    def test_get_prev_issue_with_one_item(self):
        """
        Teste da função utils.get_prev_issue() without itens, deve retorna None.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })

        issue = utils.makeOneIssue()

        # criando uma lista de fascículos vazia
        issues = [issue1]

        prev_issue = wutils.get_prev_issue(issues, issue)

        self.assertIsNone(prev_issue)

    def test_get_next_issue_with_one_item(self):
        """
        Teste da função utils.get_next_issue() without itens, deve retorna None.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })

        issue = utils.makeOneIssue()

        # criando uma lista de fascículos vazia
        issues = [issue1]

        next_issue = wutils.get_next_issue(issues, issue)

        self.assertIsNone(next_issue)

    def test_get_prev_issue_when_the_last_issue(self):
        """
        Testando o get_prev_issue quando é acessado um índice inexistente, deve
        retorna None.

        Acessando o a um índice inexistente, o último item da lista irá retornar
        None pois não existe o índice [último] + 1 (Lembrando que a lista de
        fascículo é invertida)

        Portanto a função get_prev_issue soma 1.

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })
        issue4 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '4', 'order': '4', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3, issue4]

        prev_issue = wutils.get_prev_issue(issues, issue4)

        self.assertIsNone(prev_issue)

    def test_get_next_issue_when_first_item(self):
        """
        Testando o get_next_issue quando é acessado o primiero índice, deve
        retorna None.

        Acessando o primiero item da lista irá retornar None.

        IMPORTANTE: A lista é invertida.
        """

        issue1 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '1', 'order': '1', })
        issue2 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '2', 'order': '2', })
        issue3 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '3', 'order': '3', })
        issue4 = utils.makeOneIssue({'year': '2016', 'volume': '1',
                                     'number': '4', 'order': '4', })

        # criando uma lista de fascículos ordenada
        issues = [issue1, issue2, issue3, issue4]

        next_issue = wutils.get_next_issue(issues, issue1)

        self.assertIsNone(next_issue)

    # Article
    def test_get_prev_article(self):
        """
        Teste da função utils.get_prev_article().
        """

        article1 = utils.makeOneArticle({'order': '1', })
        article2 = utils.makeOneArticle({'order': '2', })
        article3 = utils.makeOneArticle({'order': '3', })

        # criando uma lista de fascículos ordenada
        articles = [article1, article2, article3]

        prev_article = wutils.get_prev_article(articles, article2)

        self.assertEqual(prev_article, article1)

    def test_get_next_article(self):
        """
        Teste da função utils.get_next_article().
        """

        article1 = utils.makeOneArticle({'order': '1', })
        article2 = utils.makeOneArticle({'order': '2', })
        article3 = utils.makeOneArticle({'order': '3', })

        # criando uma lista de fascículos ordenada
        articles = [article1, article2, article3]

        next_article = wutils.get_next_article(articles, article2)

        self.assertEqual(next_article, article3)

    def test_get_next_article_when_last_article(self):
        """
        Teste da função utils.get_next_article(), quando é o último artigo
        deve retorna None.
        """

        article1 = utils.makeOneArticle({'order': '1', })
        article2 = utils.makeOneArticle({'order': '2', })
        article3 = utils.makeOneArticle({'order': '3', })

        # criando uma lista de fascículos ordenada
        articles = [article1, article2, article3]

        next_article = wutils.get_next_article(articles, article3)

        self.assertIsNone(next_article)

    def test_get_prev_article_when_first_article(self):
        """
        Teste da função utils.get_prev_article(), quando é o primeiro artigo
        deve retorna None.
        """

        article1 = utils.makeOneArticle({'order': '1', })
        article2 = utils.makeOneArticle({'order': '2', })
        article3 = utils.makeOneArticle({'order': '3', })

        # criando uma lista de fascículos ordenada
        articles = [article1, article2, article3]

        prev_article = wutils.get_prev_article(articles, article1)

        self.assertIsNone(prev_article)
<|endoftext|>


<commit_before>import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import tkinter.filedialog as tkfd
from pathlib2 import Path
import pgs_parser

class pgsIDEApp(tk.Tk):

    '''
    This is the main backend class
    '''

    def __init__(self, content=""):

        ''' Constructor '''

        # Call the parents constructor
        tk.Tk.__init__(self)

        # Set the window title
        tk.Tk.wm_title(self, "Pigeon IDE")

        # Set the window size
        self.geometry('{}x{}'.format(800,600))

        # Store the starting content (for when opening files)
        self.content = content

        # If the file has been saved before...
        self.has_saved = False
        # ...and where it was saved to
        self.saved_path = None

        # Create the container
        self.container = tk.Frame(self)
        self.container.pack(side="top", fill="both", expand=True)

        # And configure the grid
        self.container.grid_rowconfigure(0, weight=1)
        self.container.grid_columnconfigure(0, weight=1)

        # Create a dictionary of frames and append all pages to it
        self.frames = {}

        for f in (MainPage, RunPage):

            frame = f(self.container, self)
            self.frames[f] = frame

            frame.grid(row=0,column=0,sticky="nsew")

        # Set the starting page
        self.show_frame(MainPage)

    def show_frame(self, cont):

        # A simple function to switch pages

        frame = self.frames[cont]
        frame.tkraise()
        frame.set_menubar()

    def create_new(self, content=""):

        # Creates another isntance of this class to have multiple files open at once
        newApp = pgsIDEApp(content)
        newApp.mainloop()

class MainPage(tk.Frame):

    '''
    This is all the content on the main page
    '''

    def __init__(self, parent, controller):

        ''' Constructor '''

        # Call the parents constructor
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.controller = controller

        # Add the content

        # Fill the whole window with a text box to be typed into
        self.textArea = ScrolledText(self)
        self.textArea.pack(side="top", fill="both", expand=True)

        self.textArea.insert(tk.INSERT, self.controller.content)

        # Create the menubar and add it to the parent window
        self.menubar = tk.Menu(self.controller)
        self.set_menubar = lambda: self.controller.config(menu=self.menubar)

        # Create a 'file' menu
        self.fileMenu = tk.Menu(self.menubar)
        self.fileMenu.add_command(label="New", command=self.controller.create_new)
        self.fileMenu.add_command(label="Open", command=
                             lambda: self.controller.create_new(self.open_file())
                             )
        self.fileMenu.add_command(label="Save", command=
                             lambda: self.save_file(self.textArea.get(1.0,tk.END),True)
                             )
        self.fileMenu.add_command(label="Save As", command=
                             lambda: self.save_file(self.textArea.get(1.0,tk.END))
                             )
        self.fileMenu.add_command(label="Quit", command=None)

        # Create a 'run' menu
        self.runMenu = tk.Menu(self.menubar)
        self.runMenu.add_command(label="Run Script", command=
                            lambda: self.controller.show_frame(RunPage)
                            )

        # Add the file menu to the window
        self.menubar.add_cascade(label="File", menu=self.fileMenu)
        self.menubar.add_cascade(label="Run", menu=self.runMenu)

    def open_file(self):
        opennm = tkfd.askopenfile()
        if not opennm == None:
            f = Path(opennm.name).read_text()
            self.controller.has_saved = True
            self.controller.saved_path = opennm.name
            return f
        else:
            return ""

    def save_file(self, data, overwrite=False):

        if overwrite and self.controller.has_saved:
            f = open(self.controller.saved_path, 'w')
        else:
            f = tkfd.asksaveasfile(mode="w")
        if f is None:
            # If dialogue was closed by the 'cancel'
            return
        f.write(data)
        self.controller.has_saved = True
        self.controller.saved_path = f.name
        f.close()

class RunPage(tk.Frame):

    '''
    This is all the content on the RunPage
    '''

    def __init__(self, parent, controller):

        ''' Contstructor '''

        # Call the parents constructor
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.controller = controller

        # Add the content

        # Create an output text box
        self.outBox = ScrolledText(self)
        self.outBox.pack(side="top")
        self.outBox.config(state=tk.DISABLED)

        # Just a label
        self.errorBoxLabel = tk.Label(self, text="Error Messages:")
        self.errorBoxLabel.pack()

        # Create an error box
        self.errorBox = ScrolledText(self)
        self.errorBox.pack(side="top")
        self.errorBox.config(state=tk.DISABLED)

        # Create the menu
        self.menubar = tk.Menu(self.controller)
        self.set_menubar = lambda: self.controller.config(menu=self.menubar)

       # Create a 'file' menu
        self.fileMenu = tk.Menu(self.menubar)
        self.fileMenu.add_command(label="New", command=self.controller.create_new)
        self.fileMenu.add_command(label="Open", command=
                             lambda: self.controller.create_new(self.open_file())
                             )
        self.fileMenu.add_command(label="Quit", command=None)

        # Create a 'debug' menu
        self.debugMenu = tk.Menu(self.menubar)
        self.debugMenu.add_command(label="Show parsed code", command=None)

        # Create a 'window' menu
        self.windowMenu = tk.Menu(self.menubar)
        self.windowMenu.add_command(label="Return To Editor", command=
                               lambda: self.controller.show_frame(MainPage)
                               )

        # Add the file menu to the window
        self.menubar.add_cascade(label="File", menu=self.fileMenu)
        self.menubar.add_cascade(label="Debug", menu=self.debugMenu)
        self.menubar.add_cascade(label="Window", menu=self.windowMenu)

    def open_file(self):
        opennm = tkfd.askopenfile()
        if not opennm == None:
            f = Path(opennm.name).read_text()
            self.controller.has_saved = True
            self.controller.saved_path = opennm.name
            return f
        else:
            return ""

app = pgsIDEApp()
app.mainloop()
<commit_msg>Fixed a bug<commit_after>import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import tkinter.filedialog as tkfd
from pathlib2 import Path
import interpreter

class pgsIDEApp(tk.Tk):

    '''
    This is the main backend class
    '''

    def __init__(self, content=""):

        ''' Constructor '''

        # Call the parents constructor
        tk.Tk.__init__(self)

        # Set the window title
        tk.Tk.wm_title(self, "Pigeon IDE")

        # Set the window size
        self.geometry('{}x{}'.format(800,600))

        # Store the starting content (for when opening files)
        self.content = content

        # If the file has been saved before...
        self.has_saved = False
        # ...and where it was saved to
        self.saved_path = None

        # Create the container
        self.container = tk.Frame(self)
        self.container.pack(side="top", fill="both", expand=True)

        # And configure the grid
        self.container.grid_rowconfigure(0, weight=1)
        self.container.grid_columnconfigure(0, weight=1)

        # Create a dictionary of frames and append all pages to it
        self.frames = {}

        for f in (MainPage, RunPage):

            frame = f(self.container, self)
            self.frames[f] = frame

            frame.grid(row=0,column=0,sticky="nsew")

        # Set the starting page
        self.show_frame(MainPage)

    def show_frame(self, cont):

        # A simple function to switch pages

        frame = self.frames[cont]
        frame.tkraise()
        frame.set_menubar()

    def create_new(self, content=""):

        # Creates another isntance of this class to have multiple files open at once
        newApp = pgsIDEApp(content)
        newApp.mainloop()

class MainPage(tk.Frame):

    '''
    This is all the content on the main page
    '''

    def __init__(self, parent, controller):

        ''' Constructor '''

        # Call the parents constructor
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.controller = controller

        # Add the content

        # Fill the whole window with a text box to be typed into
        self.textArea = ScrolledText(self)
        self.textArea.pack(side="top", fill="both", expand=True)

        self.textArea.insert(tk.INSERT, self.controller.content)

        # Create the menubar and add it to the parent window
        self.menubar = tk.Menu(self.controller)
        self.set_menubar = lambda: self.controller.config(menu=self.menubar)

        # Create a 'file' menu
        self.fileMenu = tk.Menu(self.menubar)
        self.fileMenu.add_command(label="New", command=self.controller.create_new)
        self.fileMenu.add_command(label="Open", command=
                             lambda: self.controller.create_new(self.open_file())
                             )
        self.fileMenu.add_command(label="Save", command=
                             lambda: self.save_file(self.textArea.get(1.0,tk.END),True)
                             )
        self.fileMenu.add_command(label="Save As", command=
                             lambda: self.save_file(self.textArea.get(1.0,tk.END))
                             )
        self.fileMenu.add_command(label="Quit", command=None)

        # Create a 'run' menu
        self.runMenu = tk.Menu(self.menubar)
        self.runMenu.add_command(label="Run Script", command=
                            lambda: self.controller.show_frame(RunPage)
                            )

        # Add the file menu to the window
        self.menubar.add_cascade(label="File", menu=self.fileMenu)
        self.menubar.add_cascade(label="Run", menu=self.runMenu)

    def open_file(self):
        opennm = tkfd.askopenfile()
        if not opennm == None:
            f = Path(opennm.name).read_text()
            self.controller.has_saved = True
            self.controller.saved_path = opennm.name
            return f
        else:
            return ""

    def save_file(self, data, overwrite=False):

        if overwrite and self.controller.has_saved:
            f = open(self.controller.saved_path, 'w')
        else:
            f = tkfd.asksaveasfile(mode="w")
        if f is None:
            # If dialogue was closed by the 'cancel'
            return
        f.write(data)
        self.controller.has_saved = True
        self.controller.saved_path = f.name
        f.close()

class RunPage(tk.Frame):

    '''
    This is all the content on the RunPage
    '''

    def __init__(self, parent, controller):

        ''' Contstructor '''

        # Call the parents constructor
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.controller = controller

        # Add the content

        # Create an output text box
        self.outBox = ScrolledText(self)
        self.outBox.pack(side="top")
        self.outBox.config(state=tk.DISABLED)

        # Just a label
        self.errorBoxLabel = tk.Label(self, text="Error Messages:")
        self.errorBoxLabel.pack()

        # Create an error box
        self.errorBox = ScrolledText(self)
        self.errorBox.pack(side="top")
        self.errorBox.config(state=tk.DISABLED)

        # Create the menu
        self.menubar = tk.Menu(self.controller)
        self.set_menubar = lambda: self.controller.config(menu=self.menubar)

       # Create a 'file' menu
        self.fileMenu = tk.Menu(self.menubar)
        self.fileMenu.add_command(label="New", command=self.controller.create_new)
        self.fileMenu.add_command(label="Open", command=
                             lambda: self.controller.create_new(self.open_file())
                             )
        self.fileMenu.add_command(label="Quit", command=None)

        # Create a 'debug' menu
        self.debugMenu = tk.Menu(self.menubar)
        self.debugMenu.add_command(label="Show parsed code", command=None)

        # Create a 'window' menu
        self.windowMenu = tk.Menu(self.menubar)
        self.windowMenu.add_command(label="Return To Editor", command=
                               lambda: self.controller.show_frame(MainPage)
                               )

        # Add the file menu to the window
        self.menubar.add_cascade(label="File", menu=self.fileMenu)
        self.menubar.add_cascade(label="Debug", menu=self.debugMenu)
        self.menubar.add_cascade(label="Window", menu=self.windowMenu)

    def open_file(self):
        opennm = tkfd.askopenfile()
        if not opennm == None:
            f = Path(opennm.name).read_text()
            self.controller.has_saved = True
            self.controller.saved_path = opennm.name
            return f
        else:
            return ""

app = pgsIDEApp()
app.mainloop()
<|endoftext|>


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

import logging
logger = logging.getLogger(__name__)

import vtk
import numpy as nm
import yaml
import argparse
import sys

def get_cylinder(upper, height, radius,
                 direction,
                 resolution=10):

    src = vtk.vtkCylinderSource()
    src.SetCenter((0, height/2, 0))
    src.SetHeight(height + radius/2.0)
    src.SetRadius(radius)
    src.SetResolution(resolution)

    rot1 = vtk.vtkTransform()
    fi = nm.arccos(direction[1])

    rot1.RotateWXYZ(-nm.rad2deg(fi), 0.0, 0.0, 1.0)
    u = nm.abs(nm.sin(fi))
    rot2 = vtk.vtkTransform()
    if u > 1.0e-6:

        # sometimes d[0]/u little bit is over 1
        d0_over_u = direction[0] / u
        if d0_over_u > 1:
            psi = 0
        elif d0_over_u < -1:
            psi = 2 * nm.pi
        else:
            psi = nm.arccos(direction[0] / u)

        logger.debug('d0 '+str(direction[0])+'  u '+str(u)+' psi '+str(psi))
        if direction[2] < 0:
            psi = 2 * nm.pi - psi

        rot2.RotateWXYZ(-nm.rad2deg(psi), 0.0, 1.0, 0.0)

    tl = vtk.vtkTransform()
    tl.Translate(upper)

    tr1a = vtk.vtkTransformFilter()
    tr1a.SetInput(src.GetOutput())
    tr1a.SetTransform(rot1)

    tr1b = vtk.vtkTransformFilter()
    tr1b.SetInput(tr1a.GetOutput())
    tr1b.SetTransform(rot2)

    tr2 = vtk.vtkTransformFilter()
    tr2.SetInput(tr1b.GetOutput())
    tr2.SetTransform(tl)

    tr2.Update()

    return tr2.GetOutput()

def gen_tree(tree_data):

    points = vtk.vtkPoints()
    polyData = vtk.vtkPolyData()
    polyData.Allocate(1000, 1)
    polyData.SetPoints(points)
    poffset = 0

    for br in tree_data:
        cyl = get_cylinder(br['upperVertex'],
                           br['length'],
                           br['radius'],
                           br['direction'],
                           resolution=16)

        for ii in xrange(cyl.GetNumberOfPoints()):
            points.InsertPoint(poffset + ii, cyl.GetPoint(ii))

        for ii in xrange(cyl.GetNumberOfCells()):
            cell = cyl.GetCell(ii)
            cellIds = cell.GetPointIds()
            for jj in xrange(cellIds.GetNumberOfIds()):
                oldId = cellIds.GetId(jj)
                cellIds.SetId(jj, oldId + poffset)

            polyData.InsertNextCell(cell.GetCellType(),
                                    cell.GetPointIds())

        poffset += cyl.GetNumberOfPoints()

    return polyData

def process_tree(indata):
    scale = 1e-3
    scale = 1

    outdata = []
    for key in indata:
        ii = indata[key]
        logger.debug(ii)
        br = {}
        try:
            # old version of yaml tree
            vA = ii['upperVertexXYZmm']
            vB = ii['lowerVertexXYZmm']
            radi = ii['radius']
            lengthEstimation = ii['length']
        except:
            # new version of yaml
            try:
                vA = ii['nodeA_ZYX_mm']
                vB = ii['nodeB_ZYX_mm']
                radi = ii['radius_mm']
                lengthEstimation = ii['lengthEstimation']
            except:
                continue

        br['upperVertex'] = nm.array(vA) * scale
        br['radius'] = radi * scale
        br['real_length'] = lengthEstimation * scale

        vv = nm.array(vB) * scale - br['upperVertex']
        br['direction'] = vv / nm.linalg.norm(vv)
        br['length'] = nm.linalg.norm(vv)
        outdata.append(br)

    return outdata

def fix_tree_structure(tree_raw_data):
    if 'graph' in tree_raw_data:
        trees = tree_raw_data['graph']
    else:
        trees = tree_raw_data['Graph']
    return trees

def vt_file_2_vtk_file(infile, outfile, text_label=None):
    """
    From vessel_tree.yaml to output.vtk

    :param vessel_tree:  vt structure
    :param outfile: filename with .vtk extension
    :param text_label: text label like 'porta' or 'hepatic_veins'
    :return:

    """
    yaml_file = open(infile, 'r')
    tree_raw_data = yaml.load(yaml_file)
    vt2vtk_file(tree_raw_data)

def vt2vtk_file(vessel_tree, outfile, text_label=None):
    """
    vessel_tree structure
    :param vessel_tree:  vt structure
    :param outfile: filename with .vtk extension
    :param text_label: text label like 'porta' or 'hepatic_veins'
    :return:
    """
    trees = fix_tree_structure(vessel_tree)

    tkeys = trees.keys()
    if text_label is None:
        text_label = tkeys[0]

    tree_data = process_tree(trees[text_label])
    polyData = gen_tree(tree_data)

    writer = vtk.vtkPolyDataWriter()
    writer.SetFileName(outfile)
    writer.SetInput(polyData)
    writer.Write()

def main():
    logger = logging.getLogger()

    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    logger.addHandler(ch)

    # create file handler which logs even debug messages
    # fh = logging.FileHandler('log.txt')
    # fh.setLevel(logging.DEBUG)
    # formatter = logging.Formatter(
    #     '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    # fh.setFormatter(formatter)
    # logger.addHandler(fh)
    # logger.debug('start')

    # input parser
    parser = argparse.ArgumentParser(
        description=__doc__
    )
    parser.add_argument(
        'inputfile',
        default=None,
        required=True,
        help='input file'
    )
    parser.add_argument(
        'outputfile',
        default='output.vtk',
        required=False,
        help='output file'
    )
    parser.add_argument(
        '-l','--label',
        default=None,
        help='text label of vessel tree. f.e. "porta" or "hepatic_veins". \
        First label is used if it is set to None'
    )
    parser.add_argument(
        '-d', '--debug', action='store_true',
        help='Debug mode')
    args = parser.parse_args()

    if args.debug:
        ch.setLevel(logging.DEBUG)

    vt_file_2_vtk_file(args.inputfile, args.outputfile, args.label)

if __name__ == "__main__":
    main()
<commit_msg>argparse params<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
logger = logging.getLogger(__name__)

import vtk
import numpy as nm
import yaml
import argparse
import sys

def get_cylinder(upper, height, radius,
                 direction,
                 resolution=10):

    src = vtk.vtkCylinderSource()
    src.SetCenter((0, height/2, 0))
    src.SetHeight(height + radius/2.0)
    src.SetRadius(radius)
    src.SetResolution(resolution)

    rot1 = vtk.vtkTransform()
    fi = nm.arccos(direction[1])

    rot1.RotateWXYZ(-nm.rad2deg(fi), 0.0, 0.0, 1.0)
    u = nm.abs(nm.sin(fi))
    rot2 = vtk.vtkTransform()
    if u > 1.0e-6:

        # sometimes d[0]/u little bit is over 1
        d0_over_u = direction[0] / u
        if d0_over_u > 1:
            psi = 0
        elif d0_over_u < -1:
            psi = 2 * nm.pi
        else:
            psi = nm.arccos(direction[0] / u)

        logger.debug('d0 '+str(direction[0])+'  u '+str(u)+' psi '+str(psi))
        if direction[2] < 0:
            psi = 2 * nm.pi - psi

        rot2.RotateWXYZ(-nm.rad2deg(psi), 0.0, 1.0, 0.0)

    tl = vtk.vtkTransform()
    tl.Translate(upper)

    tr1a = vtk.vtkTransformFilter()
    tr1a.SetInput(src.GetOutput())
    tr1a.SetTransform(rot1)

    tr1b = vtk.vtkTransformFilter()
    tr1b.SetInput(tr1a.GetOutput())
    tr1b.SetTransform(rot2)

    tr2 = vtk.vtkTransformFilter()
    tr2.SetInput(tr1b.GetOutput())
    tr2.SetTransform(tl)

    tr2.Update()

    return tr2.GetOutput()

def gen_tree(tree_data):

    points = vtk.vtkPoints()
    polyData = vtk.vtkPolyData()
    polyData.Allocate(1000, 1)
    polyData.SetPoints(points)
    poffset = 0

    for br in tree_data:
        cyl = get_cylinder(br['upperVertex'],
                           br['length'],
                           br['radius'],
                           br['direction'],
                           resolution=16)

        for ii in xrange(cyl.GetNumberOfPoints()):
            points.InsertPoint(poffset + ii, cyl.GetPoint(ii))

        for ii in xrange(cyl.GetNumberOfCells()):
            cell = cyl.GetCell(ii)
            cellIds = cell.GetPointIds()
            for jj in xrange(cellIds.GetNumberOfIds()):
                oldId = cellIds.GetId(jj)
                cellIds.SetId(jj, oldId + poffset)

            polyData.InsertNextCell(cell.GetCellType(),
                                    cell.GetPointIds())

        poffset += cyl.GetNumberOfPoints()

    return polyData

def process_tree(indata):
    scale = 1e-3
    scale = 1

    outdata = []
    for key in indata:
        ii = indata[key]
        logger.debug(ii)
        br = {}
        try:
            # old version of yaml tree
            vA = ii['upperVertexXYZmm']
            vB = ii['lowerVertexXYZmm']
            radi = ii['radius']
            lengthEstimation = ii['length']
        except:
            # new version of yaml
            try:
                vA = ii['nodeA_ZYX_mm']
                vB = ii['nodeB_ZYX_mm']
                radi = ii['radius_mm']
                lengthEstimation = ii['lengthEstimation']
            except:
                continue

        br['upperVertex'] = nm.array(vA) * scale
        br['radius'] = radi * scale
        br['real_length'] = lengthEstimation * scale

        vv = nm.array(vB) * scale - br['upperVertex']
        br['direction'] = vv / nm.linalg.norm(vv)
        br['length'] = nm.linalg.norm(vv)
        outdata.append(br)

    return outdata

def fix_tree_structure(tree_raw_data):
    if 'graph' in tree_raw_data:
        trees = tree_raw_data['graph']
    else:
        trees = tree_raw_data['Graph']
    return trees

def vt_file_2_vtk_file(infile, outfile, text_label=None):
    """
    From vessel_tree.yaml to output.vtk

    :param vessel_tree:  vt structure
    :param outfile: filename with .vtk extension
    :param text_label: text label like 'porta' or 'hepatic_veins'
    :return:

    """
    yaml_file = open(infile, 'r')
    tree_raw_data = yaml.load(yaml_file)
    vt2vtk_file(tree_raw_data)

def vt2vtk_file(vessel_tree, outfile, text_label=None):
    """
    vessel_tree structure
    :param vessel_tree:  vt structure
    :param outfile: filename with .vtk extension
    :param text_label: text label like 'porta' or 'hepatic_veins'
    :return:
    """
    trees = fix_tree_structure(vessel_tree)

    tkeys = trees.keys()
    if text_label is None:
        text_label = tkeys[0]

    tree_data = process_tree(trees[text_label])
    polyData = gen_tree(tree_data)

    writer = vtk.vtkPolyDataWriter()
    writer.SetFileName(outfile)
    writer.SetInput(polyData)
    writer.Write()

def main():
    logger = logging.getLogger()

    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    logger.addHandler(ch)

    # create file handler which logs even debug messages
    # fh = logging.FileHandler('log.txt')
    # fh.setLevel(logging.DEBUG)
    # formatter = logging.Formatter(
    #     '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    # fh.setFormatter(formatter)
    # logger.addHandler(fh)
    # logger.debug('start')

    # input parser
    parser = argparse.ArgumentParser(
        description=__doc__
    )
    parser.add_argument(
        'inputfile',
        default=None,
        required=True,
        help='input file'
    )
    parser.add_argument(
        'outputfile',
        default='output.vtk',
        nargs='?',
        help='output file'
    )
    parser.add_argument(
        '-l','--label',
        default=None,
        help='text label of vessel tree. f.e. "porta" or "hepatic_veins". \
        First label is used if it is set to None'
    )
    parser.add_argument(
        '-d', '--debug', action='store_true',
        help='Debug mode')
    args = parser.parse_args()

    if args.debug:
        ch.setLevel(logging.DEBUG)

    vt_file_2_vtk_file(args.inputfile, args.outputfile, args.label)

if __name__ == "__main__":
    main()
<|endoftext|>