<commit_before># Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
Contains a class to handle a validation result for a single VOTable
file.
"""

from __future__ import absolute_import

# STDLIB
from xml.parsers.expat import ExpatError
import hashlib
import httplib
import os
import cPickle as pickle
import shutil
import socket
import subprocess
import urllib2
import warnings

# VO
from .. import table
from .. import exceptions
from .. import xmlutil
from ..util import IS_PY3K


class Result:
    def __init__(self, url, root='results', timeout=10):
        self.url = url
        m = hashlib.md5()
        m.update(url)
        self._hash = m.hexdigest()
        self._root = root
        self._path = os.path.join(
            self._hash[0:2], self._hash[2:4], self._hash[4:])
        if not os.path.exists(self.get_dirpath()):
            os.makedirs(self.get_dirpath())
        self.timeout = timeout
        self.load_attributes()

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.save_attributes()

    def get_dirpath(self):
        return os.path.join(self._root, self._path)

    def get_htmlpath(self):
        return self._path

    def get_attribute_path(self):
        return os.path.join(self.get_dirpath(), "values.dat")

    def get_vo_xml_path(self):
        return os.path.join(self.get_dirpath(), "vo.xml")

    # ATTRIBUTES

    def load_attributes(self):
        path = self.get_attribute_path()
        if os.path.exists(path):
            try:
                with open(path, 'rb') as fd:
                    self._attributes = pickle.load(fd)
            except:
                shutil.rmtree(self.get_dirpath())
                os.makedirs(self.get_dirpath())
                self._attributes = {}
        else:
            self._attributes = {}

    def save_attributes(self):
        path = self.get_attribute_path()
        with open(path, 'wb') as fd:
            pickle.dump(self._attributes, fd)

    def __getitem__(self, key):
        return self._attributes[key]

    def __setitem__(self, key, val):
        self._attributes[key] = val

    def __contains__(self, key):
        return key in self._attributes

    # VO XML

    def download_xml_content(self):
        path = self.get_vo_xml_path()

        if 'network_error' not in self._attributes:
            self['network_error'] = None

        if os.path.exists(path):
            return

        def fail(reason):
            reason = str(reason)
            with open(path, 'wb') as fd:
                fd.write('FAILED: {}\n'.format(reason).encode('utf-8'))
            self['network_error'] = reason

        r = None
        try:
            if IS_PY3K:
                r = urllib2.urlopen(self.url.decode('ascii'),
                                    timeout=self.timeout)
            else:<commit_msg>minor formatting syntax for backward compatibility<commit_after># Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
Contains a class to handle a validation result for a single VOTable
file.
"""

from __future__ import absolute_import

# STDLIB
from xml.parsers.expat import ExpatError
import hashlib
import httplib
import os
import cPickle as pickle
import shutil
import socket
import subprocess
import urllib2
import warnings

# VO
from .. import table
from .. import exceptions
from .. import xmlutil
from ..util import IS_PY3K


class Result:
    def __init__(self, url, root='results', timeout=10):
        self.url = url
        m = hashlib.md5()
        m.update(url)
        self._hash = m.hexdigest()
        self._root = root
        self._path = os.path.join(
            self._hash[0:2], self._hash[2:4], self._hash[4:])
        if not os.path.exists(self.get_dirpath()):
            os.makedirs(self.get_dirpath())
        self.timeout = timeout
        self.load_attributes()

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.save_attributes()

    def get_dirpath(self):
        return os.path.join(self._root, self._path)

    def get_htmlpath(self):
        return self._path

    def get_attribute_path(self):
        return os.path.join(self.get_dirpath(), "values.dat")

    def get_vo_xml_path(self):
        return os.path.join(self.get_dirpath(), "vo.xml")

    # ATTRIBUTES

    def load_attributes(self):
        path = self.get_attribute_path()
        if os.path.exists(path):
            try:
                with open(path, 'rb') as fd:
                    self._attributes = pickle.load(fd)
            except:
                shutil.rmtree(self.get_dirpath())
                os.makedirs(self.get_dirpath())
                self._attributes = {}
        else:
            self._attributes = {}

    def save_attributes(self):
        path = self.get_attribute_path()
        with open(path, 'wb') as fd:
            pickle.dump(self._attributes, fd)

    def __getitem__(self, key):
        return self._attributes[key]

    def __setitem__(self, key, val):
        self._attributes[key] = val

    def __contains__(self, key):
        return key in self._attributes

    # VO XML

    def download_xml_content(self):
        path = self.get_vo_xml_path()

        if 'network_error' not in self._attributes:
            self['network_error'] = None

        if os.path.exists(path):
            return

        def fail(reason):
            reason = str(reason)
            with open(path, 'wb') as fd:
                fd.write('FAILED: {0}\n'.format(reason).encode('utf-8'))
            self['network_error'] = reason

        r = None
        try:
            if IS_PY3K:
                r = urllib2.urlopen(self.url.decode('ascii'),
                                    timeout=self.timeout)
            else:
{'fraction_non_alphanumeric': 0.10590277777777778, 'fraction_numerical': 0.0050347222222222225, 'mean_word_length': 2.061105207226355, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 12}, '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': '3937972', 'n_tokens_mistral': 1767, 'n_tokens_neox': 1696, 'n_words': 422}