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

import Image
import ImageFont
import ImageDraw
try:
    from collections import namedtuple
except ImportError:
    from utils.namedtuple import namedtuple


XY = namedtuple('XY', 'x y')

class FoldedTextDraw(ImageDraw.ImageDraw):
    def __init__(self, im, mode=None):
        ImageDraw.ImageDraw.__init__(self, im, mode)

    def text(self, box, string, **kwargs):
        ttfont = kwargs.get('font')
        lineSpacing = kwargs.get('lineSpacing', 2)
        size = (box[2] - box[0], box[3] - box[1])

        lines = self._getFoldedText(size, string,
                                    font=ttfont, lineSpacing=lineSpacing)

        height = 0
        for string in lines:
            height += self.textsize(string, font=ttfont)[1] + lineSpacing

        height = (size[1] - (height - lineSpacing)) / 2
        xy = (box[0], box[1])
        for string in lines:
            textsize = self.textsize(string, font=ttfont)
            x = (size[0] - textsize[0]) / 2

            draw_xy = (xy[0] + x, xy[1] + height)
            ImageDraw.ImageDraw.text(self, draw_xy, string,
                                     fill=self.fill, font=ttfont)

            height += textsize[1] + lineSpacing

    def _getFoldedText(self, size, string, **kwargs):
        ttfont = kwargs.get('font')
        lineSpacing = kwargs.get('lineSpacing', 2)
        lines = []

        height = 0
        truncated = 0
        for line in string.splitlines():
            while line:
                string = string.strip()
                for i in range(0, len(string)):
                    length = len(string) - i
                    metrics = self.textsize(string[0:length], font=ttfont)

                    if metrics[0] <= size[0]:
                        break

                if size[1] < height + metrics[1]:
                    truncated = 1
                    break

                lines.append(line[0:length])
                line = line[length:]

                height += metrics[1] + lineSpacing

        # truncate last line.
        if truncated:
            string = lines.pop()
            for i in range(0, len(string)):
                if i == 0:
                    truncated = string + ' ...'
                else:
                    truncated = string[0:-i] + ' ...'

                size = self.textsize(truncated, font=ttfont)
                if size[0] <= size[0]:
                    lines.append(truncated)
                    break

        return lines


class DiagramMetrix:
    def __init__(self, **kwargs):
        self.cellSize = kwargs.get('cellSize', 8)
        self.pageMargin = kwargs.get('pageMargin', 2)
        self.nodePadding = kwargs.get('nodePadding', 4)
        self.nodeColumns = kwargs.get('nodeColumns', 16)
        self.nodeRows = kwargs.get('nodeRows', 4)
        self.spanColumns = kwargs.get('spanColumns', 8)
        self.spanRows = kwargs.get('spanRows', 3)

        self.pageMargin = self.cellSize * self.pageMargin
        self.nodeWidth = self.cellSize * self.nodeColumns
        self.nodeHeight = self.cellSize * self.nodeRows
        self.spanWidth = self.cellSize * self.spanColumns
        self.spanHeight = self.cellSize * self.spanRows

    def node(self, node):
        return NodeMetrix(node, self)

    def pageSize(self, nodelist):
        x = 0
        y = 0
        for node in nodelist:
            if x <= node.xy[0]:
                x = node.xy[0]
            if y <= node.xy[1]:
                y = node.xy[1]

        x, y = NodeMetrix.new2(x, y, self).bottomRight()
        return (x + self.pageMargin, y + self.pageMargin)


class NodeMetrix:
    @classmethod
    def new2(klass, x, y, metrix):
        o = klass(None, metrix)
        (o.x, o.y) = klass._topLeft(x, y, metrix)

        return o

    def __init__(self, node, metrix):
        self.metrix = metrix

        if node:
            (self.x, self.y) = self._topLeft(node.xy[0], node.xy[1], metrix)

    @classmethod
    def _topLeft(klass, x, y, metrix):
        x = metrix.pageMargin + x * (metrix.nodeWidth + metrix.spanWidth)
        y = metrix.pageMargin + y * (metrix.nodeHeight + metrix.spanHeight)

        return XY(x, y)

    def coreBox(self):
        m = self.metrix
        x, y = self.topLeft()

        return (x + m.nodePadding,
                y + m.nodePadding,
                x + m.nodeWidth - m.nodePadding * 2,
                y + m.nodeHeight - m.nodePadding * 2)

    def topLeft(self):
        return XY(self.x, self.y)

    def topCenter(self):
        x, y = self.topLeft()
        return XY(x + self.metrix.nodeWidth / 2, y)

    def topRight(self):
        x, y = self.topLeft()
        return XY(x + self.metrix.nodeWidth, y)

    def bottomLeft(self):
        x, y = self.topLeft()
        return XY(x, y + self.metrix.nodeHeight)

    def bottomCenter(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth / 2, y + m.nodeHeight)

    def bottomRight(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth, y + m.nodeHeight)

    def leftCenter(self):
        x, y = self.topLeft()
        return XY(x, y + self.metrix.nodeHeight / 2)

    def rightCenter(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth, y + m.nodeHeight / 2)

    # method aliases
    top = topCenter;
    bottom = bottomCenter;
    right = rightCenter;
    left = leftCenter;


class xylist(list):
    def add(self, x, y=None):
        if y:
            self.append((x, y))
        else:
            self.append(x)


class DiagramDraw(ImageDraw.ImageDraw):
    def __init__(self, im, mode=None, **kwargs):
        self.image = im
        self.metrix = DiagramMetrix(**kwargs)
        self.lineSpacing = kwargs.get('lineSpacing', 2)
        self.fill = kwargs.get('fill', (0, 0, 0))

        ImageDraw.ImageDraw.__init__(self, im, mode)

    def getPaperSize(self, root):
        return self.metrix.pageSize(root)

    def screennode(self, node, **kwargs):
        ttfont = kwargs.get('font')

        metrix = self.metrix.node(node)
        if node.color:
            self.rectangle([metrix.topLeft(), metrix.bottomRight()], outline=self.fill, fill=node.color)
        else:
            self.rectangle([metrix.topLeft(), metrix.bottomRight()], outline=self.fill)

        box = self.metrix.node(node).coreBox()
        draw = FoldedTextDraw(self.image)
        draw.text(box, node.label, font=ttfont, lineSpacing=self.lineSpacing)

    def screennodelist(self, nodelist, **kwargs):
        for node in nodelist:
            self.screennode(node, **kwargs)

    def edge(self, edge):
        lines = xylist()
        head = xylist()
        cell = self.metrix.cellSize
        span = XY(self.metrix.spanWidth, self.metrix.spanHeight)

        node1 = self.metrix.node(edge.node1)
        node2 = self.metrix.node(edge.node2)

        if node1.x < node2.x:<commit_msg> * Fix to support PEP-8.<commit_after>#!/usr/bin/python
# -*- encoding: utf-8 -*-

import Image
import ImageFont
import ImageDraw
try:
    from collections import namedtuple
except ImportError:
    from utils.namedtuple import namedtuple


XY = namedtuple('XY', 'x y')


class FoldedTextDraw(ImageDraw.ImageDraw):
    def __init__(self, im, mode=None):
        ImageDraw.ImageDraw.__init__(self, im, mode)

    def text(self, box, string, **kwargs):
        ttfont = kwargs.get('font')
        lineSpacing = kwargs.get('lineSpacing', 2)
        size = (box[2] - box[0], box[3] - box[1])

        lines = self._getFoldedText(size, string,
                                    font=ttfont, lineSpacing=lineSpacing)

        height = 0
        for string in lines:
            height += self.textsize(string, font=ttfont)[1] + lineSpacing

        height = (size[1] - (height - lineSpacing)) / 2
        xy = (box[0], box[1])
        for string in lines:
            textsize = self.textsize(string, font=ttfont)
            x = (size[0] - textsize[0]) / 2

            draw_xy = (xy[0] + x, xy[1] + height)
            ImageDraw.ImageDraw.text(self, draw_xy, string,
                                     fill=self.fill, font=ttfont)

            height += textsize[1] + lineSpacing

    def _getFoldedText(self, size, string, **kwargs):
        ttfont = kwargs.get('font')
        lineSpacing = kwargs.get('lineSpacing', 2)
        lines = []

        height = 0
        truncated = 0
        for line in string.splitlines():
            while line:
                string = string.strip()
                for i in range(0, len(string)):
                    length = len(string) - i
                    metrics = self.textsize(string[0:length], font=ttfont)

                    if metrics[0] <= size[0]:
                        break

                if size[1] < height + metrics[1]:
                    truncated = 1
                    break

                lines.append(line[0:length])
                line = line[length:]

                height += metrics[1] + lineSpacing

        # truncate last line.
        if truncated:
            string = lines.pop()
            for i in range(0, len(string)):
                if i == 0:
                    truncated = string + ' ...'
                else:
                    truncated = string[0:-i] + ' ...'

                size = self.textsize(truncated, font=ttfont)
                if size[0] <= size[0]:
                    lines.append(truncated)
                    break

        return lines


class DiagramMetrix:
    def __init__(self, **kwargs):
        self.cellSize = kwargs.get('cellSize', 8)
        self.pageMargin = kwargs.get('pageMargin', 2)
        self.nodePadding = kwargs.get('nodePadding', 4)
        self.nodeColumns = kwargs.get('nodeColumns', 16)
        self.nodeRows = kwargs.get('nodeRows', 4)
        self.spanColumns = kwargs.get('spanColumns', 8)
        self.spanRows = kwargs.get('spanRows', 3)

        self.pageMargin = self.cellSize * self.pageMargin
        self.nodeWidth = self.cellSize * self.nodeColumns
        self.nodeHeight = self.cellSize * self.nodeRows
        self.spanWidth = self.cellSize * self.spanColumns
        self.spanHeight = self.cellSize * self.spanRows

    def node(self, node):
        return NodeMetrix(node, self)

    def pageSize(self, nodelist):
        x = 0
        y = 0
        for node in nodelist:
            if x <= node.xy[0]:
                x = node.xy[0]
            if y <= node.xy[1]:
                y = node.xy[1]

        x, y = NodeMetrix.new2(x, y, self).bottomRight()
        return (x + self.pageMargin, y + self.pageMargin)


class NodeMetrix:
    @classmethod
    def new2(klass, x, y, metrix):
        o = klass(None, metrix)
        (o.x, o.y) = klass._topLeft(x, y, metrix)

        return o

    def __init__(self, node, metrix):
        self.metrix = metrix

        if node:
            (self.x, self.y) = self._topLeft(node.xy[0], node.xy[1], metrix)

    @classmethod
    def _topLeft(klass, x, y, metrix):
        x = metrix.pageMargin + x * (metrix.nodeWidth + metrix.spanWidth)
        y = metrix.pageMargin + y * (metrix.nodeHeight + metrix.spanHeight)

        return XY(x, y)

    def coreBox(self):
        m = self.metrix
        x, y = self.topLeft()

        return (x + m.nodePadding,
                y + m.nodePadding,
                x + m.nodeWidth - m.nodePadding * 2,
                y + m.nodeHeight - m.nodePadding * 2)

    def topLeft(self):
        return XY(self.x, self.y)

    def topCenter(self):
        x, y = self.topLeft()
        return XY(x + self.metrix.nodeWidth / 2, y)

    def topRight(self):
        x, y = self.topLeft()
        return XY(x + self.metrix.nodeWidth, y)

    def bottomLeft(self):
        x, y = self.topLeft()
        return XY(x, y + self.metrix.nodeHeight)

    def bottomCenter(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth / 2, y + m.nodeHeight)

    def bottomRight(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth, y + m.nodeHeight)

    def leftCenter(self):
        x, y = self.topLeft()
        return XY(x, y + self.metrix.nodeHeight / 2)

    def rightCenter(self):
        m = self.metrix
        x, y = self.topLeft()
        return XY(x + m.nodeWidth, y + m.nodeHeight / 2)

    # method aliases
    top = topCenter
    bottom = bottomCenter
    right = rightCenter
    left = leftCenter


class xylist(list):
    def add(self, x, y=None):
        if y:
            self.append((x, y))
        else:
            self.append(x)


class DiagramDraw(ImageDraw.ImageDraw):
    def __init__(self, im, mode=None, **kwargs):
        self.image = im
        self.metrix = DiagramMetrix(**kwargs)
        self.lineSpacing = kwargs.get('lineSpacing', 2)
        self.fill = kwargs.get('fill', (0, 0, 0))

        ImageDraw.ImageDraw.__init__(self, im, mode)

    def getPaperSize(self, root):
        return self.metrix.pageSize(root)

    def screennode(self, node, **kwargs):
        ttfont = kwargs.get('font')

        metrix = self.metrix.node(node)
        box = [metrix.topLeft(), metrix.bottomRight()]
        if node.color:
            self.rectangle(box, outline=self.fill, fill=node.color)
        else:
            self.rectangle(box, outline=self.fill)

        box = self.metrix.node(node).coreBox()
        draw = FoldedTextDraw(self.image)
        draw.text(box, node.label, font=ttfont, lineSpacing=self.lineSpacing)

    def screennodelist(self, nodelist, **kwargs):
        for node in nodelist:
            self.screennode(node, **kwargs)

    def edge(self, edge):
        lines = xylist()
        head = xylist()
        cell = self.metrix.cellSize
        span = XY(self.metrix.spanWidth, self.metrix.spanHeight)

        node1 = self.metrix.node(edge.node1)
        node2 = self.metrix.node(edge.node2)

        if node1.x < node2.x:
{'fraction_non_alphanumeric': 0.12404046201305689, 'fraction_numerical': 0.009972020948418108, 'mean_word_length': 1.820149706655877, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '638801', 'n_tokens_mistral': 4562, 'n_tokens_neox': 4349, 'n_words': 1022}