<commit_before>import time
import Queue
import socket
import logging

import signals
from stoppable import StoppableLoopThread
from packeter import packeter
from utils import big_endian_to_int as idec
from utils import recursive_int_to_big_endian
import rlp
import blocks

# Maximum number of send hashes GetChain will accept
MAX_GET_CHAIN_ACCEPT_HASHES = 2048
# Maximum number of hashes GetChain will ever send
MAX_GET_CHAIN_SEND_HASHES = 2048
# Maximum number of blocks GetChain will ever ask for
MAX_GET_CHAIN_ASK_BLOCKS = 512
# Maximum number of requested blocks GetChain will accept
MAX_GET_CHAIN_REQUEST_BLOCKS = 512
# Maximum number of blocks Blocks will ever send
MAX_BLOCKS_SEND = MAX_GET_CHAIN_REQUEST_BLOCKS
# Maximum number of blocks Blocks will ever accept
MAX_BLOCKS_ACCEPTED = MAX_BLOCKS_SEND

logger = logging.getLogger(__name__)

class Peer(StoppableLoopThread):

    def __init__(self, connection, ip, port):
        super(Peer, self).__init__()
        self._connection = connection

        assert ip.count('.') == 3
        self.ip = ip
        # None if peer was created in response to external connect
        self.port = port
        self.client_version = ''
        self.node_id = ''
        self.capabilities = []  # [('eth',40) , ('shh',12)]

        self.hello_received = False
        self.hello_sent = False
        self.last_valid_packet_received = time.time()
        self.last_asked_for_peers = 0
        self.last_pinged = 0
        self.status_received = False
        self.status_sent = False
        self.status_total_difficulty = None
        self.status_head_hash = None

        self.recv_buffer = ''
        self.response_queue = Queue.Queue()

    def __repr__(self):
        return "<Peer(%s:%r)>" % (self.ip, self.port)

    def __str__(self):
        return "[{0}: {1}]".format(self.ip, self.port)

    def connection(self):
        if self.stopped():
            raise IOError("Connection was stopped")
        else:
            return self._connection

    def stop(self):
        super(Peer, self).stop()

        # shut down
        try:
            self._connection.shutdown(socket.SHUT_RDWR)
        except socket.error as e:
            logger.debug("shutting down failed %r '%s'", self, e)
        self._connection.close()

    def send_packet(self, response):
        logger.debug('sending %r >>> %s', self, packeter.packet_cmd(response))
        self.response_queue.put(response)

    def _process_send(self):
        '''
        :return: size of processed data
        '''
        # send packet
        try:
            packet = self.response_queue.get(block=False)
        except Queue.Empty:
            return 0
        try:
            self.connection().sendall(packet)
            return len(packet)
        except socket.error as e:
            logger.debug('%r: send packet failed, %s', self, e)
            self.stop()
            return 0

    def _process_recv(self):
        '''
        :return: size of processed data
        '''
        # receive complete message
        processed_length = 0
        while True:
            try:
                # print 'receiving'
                self.recv_buffer += self.connection().recv(2048)
            except socket.error:  # Timeout
                # print 'timeout'
                break
            # check if we have a complete packet
            length = len(self.recv_buffer)
            # length > packet_header and length > expected packet size
            while len(self.recv_buffer) >= 8 and len(self.recv_buffer) >= packeter.packet_size(self.recv_buffer):
                processed_length += packeter.packet_size(self.recv_buffer)
                self._process_recv_buffer()

        return processed_length

    def _process_recv_buffer(self):
        try:
            cmd, data, self.recv_buffer = packeter.load_cmd(self.recv_buffer)
        except Exception as e:
            self.recv_buffer = ''
            logger.warn(e)
            return self.send_Disconnect(reason='Bad protocol')

        # good peer
        self.last_valid_packet_received = time.time()
        logger.debug('receive %r <<< %s (%d)', self, cmd, len(data))
        func_name = "_recv_{0}".format(cmd)
        if not hasattr(self, func_name):
            logger.warn('unknown cmd "%s"', cmd)
            return
        getattr(self, func_name)(data)

    # Handshake
    def has_ethereum_capabilities(self):
        for p, pv in self.capabilities:
            if p == 'eth' and pv == packeter.ETHEREUM_PROTOCOL_VERSION:
                return True

    def send_Hello(self):
        logger.debug('%r sending Hello', self)
        self.send_packet(packeter.dump_Hello())
        self.hello_sent = True

    def _recv_Hello(self, data):
        # 0x01 Hello: [0x01: P, protocolVersion: P, clientVersion: B, [cap0: B, cap1: B, ...], listenPort: P, id: B_64]
        _decode = (idec, str, list, idec, str)
        try:
            data = [_decode[i](x) for i, x in enumerate(data)]
            network_protocol_version, client_version = data[0], data[1]
            capabilities, listen_port, node_id = data[2], data[3], data[4]
        except IndexError:
            return self.send_Disconnect(reason='Incompatible network protocols')

        self.capabilities = [(p,ord(v)) for p, v in capabilities]
        logger.debug('%r received Hello PROTOCOL:%r NODE_ID:%r CLIENT_VERSION:%r CAPABILITIES:%r',
                     self, network_protocol_version, node_id.encode('hex')[:8], client_version, self.capabilities)

        if network_protocol_version != packeter.NETWORK_PROTOCOL_VERSION:
            logger.debug('%r Incompatible network protocols, expected %r, received %r',
                         self, packeter.NETWORK_PROTOCOL_VERSION, network_protocol_version)

            return self.send_Disconnect(reason='Incompatible network protocols')

        self.hello_received = True
        self.client_version = client_version
        self.node_id = node_id
        self.port = listen_port  # replace connection port with listen port

        if not self.hello_sent:
            self.send_Hello()
        signals.peer_handshake_success.send(sender=Peer, peer=self)

# Status

    def send_Status(self, head_hash, head_total_difficulty, genesis_hash):
        logger.debug('sending status TD:%d HEAD:%r GENESIS:%r',
                     head_total_difficulty, head_hash.encode('hex'), genesis_hash.encode('hex'))

        self.send_packet(packeter.dump_Status(head_total_difficulty, head_hash, genesis_hash))
        self.status_sent = True

    def _recv_Status(self, data):
        # [0x10: P, protocolVersion: P, networkID: P, totalDifficulty: P, latestHash: B_32, genesisHash: B_32]
        # check compatibility
        try:
            ethereum_protocol_version, network_id = idec(data[0]), idec(data[1])
            total_difficulty, head_hash, genesis_hash = idec(data[2]), data[3], data[4]
        except IndexError:
            return self.send_Disconnect(reason='Incompatible network protocols')

        logger.debug('%r, received Status ETHPROTOCOL:%r TD:%d HEAD:%r GENESIS:%r',
                     self, ethereum_protocol_version, total_difficulty,
                     head_hash.encode('hex'), genesis_hash.encode('hex'))

        if ethereum_protocol_version != packeter.ETHEREUM_PROTOCOL_VERSION:
            return self.send_Disconnect(reason='Incompatible network protocols')

        if network_id != packeter.NETWORK_ID:
            return self.send_Disconnect(reason='Wrong genesis block')

        if genesis_hash != blocks.genesis().hash:
            return self.send_Disconnect(reason='Wrong genesis block')

        self.status_received = True
        self.status_head_hash = head_hash
        self.status_total_difficulty = total_difficulty
        signals.peer_status_received.send(sender=Peer, peer=self)

# ping pong

    def send_Ping(self):
        self.send_packet(packeter.dump_Ping())
        self.last_pinged = time.time()

    def _recv_Ping(self, data):
        self.send_Pong()

    def send_Pong(self):
        self.send_packet(packeter.dump_Pong())

    def _recv_Pong(self, data):
        pass

# disconnects
    reasons_to_forget = ('Bad protocol',
                         'Incompatible network protocols',
                         'Wrong genesis block')

    def send_Disconnect(self, reason=None):
        logger.info('%r sending disconnect: %r', self, reason)
        self.send_packet(packeter.dump_Disconnect(reason=reason))
        # end connection
        time.sleep(2)
        forget = reason in self.reasons_to_forget
        signals.peer_disconnect_requested.send(Peer, peer=self, forget=forget)

    def _recv_Disconnect(self, data):
        if len(data):
            reason = packeter.disconnect_reasons_map_by_id[idec(data[0])]
            logger.info('%r received disconnect: %r', self, reason)
            forget = reason in self.reasons_to_forget
        else:
            forget = None
            logger.info('%r received disconnect: w/o reason', self)
        signals.peer_disconnect_requested.send(sender=Peer, peer=self, forget=forget)

# peers

    def send_GetPeers(self):
        self.send_packet(packeter.dump_GetPeers())

    def _recv_GetPeers(self, data):
        signals.getpeers_received.send(sender=Peer, peer=self)

    def send_Peers(self, peers):
        if peers:
            packet = packeter.dump_Peers(peers)
            self.send_packet(packet)

    def _recv_Peers(self, data):
        addresses = []
        for ip, port, pid in data:
            assert len(ip) == 4
            ip = '.'.join(str(ord(b)) for b in ip)
            port = idec(port)
            logger.debug('received peer address: {0}:{1}'.format(ip, port))
            addresses.append([ip, port, pid])
        signals.peer_addresses_received.send(sender=Peer, addresses=addresses)

# transactions

    def send_Transactions(self, transactions):
        self.send_packet(packeter.dump_Transactions(transactions))

    def _recv_Transactions(self, data):
        logger.debug('received transactions #%d', len(data))
        signals.remote_transactions_received.send(sender=Peer, transactions=data, peer=self)

# blocks

    def send_Blocks(self, blocks):
        assert len(blocks) <= MAX_BLOCKS_SEND
        self.send_packet(packeter.dump_Blocks(blocks))

    def _recv_Blocks(self, data):
        # open('raw_remote_blocks_hex.txt', 'a').write(rlp.encode(data).encode('hex') + '\n') # LOG line
        transient_blocks = [blocks.TransientBlock(rlp.encode(b)) for b in data]  # FIXME
        if len(transient_blocks) > MAX_BLOCKS_ACCEPTED:
            logger.warn('Peer sending too many blocks %d', len(transient_blocks))
        signals.remote_blocks_received.send(sender=Peer, peer=self, transient_blocks=transient_blocks)

    def send_GetBlocks(self, block_hashes):
        self.send_packet(packeter.dump_GetBlocks(block_hashes))

    def _recv_GetBlocks(self, block_hashes):
        signals.get_blocks_received.send(
            sender=Peer, block_hashes=block_hashes, peer=self)

# new blocks
    def send_NewBlock(self, block):
        self.send_packet(packeter.dump_NewBlock(block))

    def _recv_NewBlock(self, data):
        logger.debug('NewBlock: %r', rlp.encode(data).encode('hex'))
        total_difficulty = idec(data[1])
        transient_block = blocks.TransientBlock(rlp.encode(data[0]))
        signals.new_block_received.send(
            sender=Peer, peer=self, block=transient_block)

# block hashes
    def send_GetBlockHashes(self, block_hash, max_blocks):
        self.send_packet(packeter.dump_GetBlockHashes(block_hash, max_blocks))

    def _recv_GetBlockHashes(self, data):
        block_hash, count = data[0], idec(data[1])
        signals.get_block_hashes_received.send(sender=Peer, block_hash=block_hash, count=count, peer=self)

    def send_BlockHashes(self, block_hashes):
        self.send_packet(packeter.dump_BlockHashes(block_hashes))

    def _recv_BlockHashes(self, block_hashes):
        signals.remote_block_hashes_received.send(sender=Peer, block_hashes=block_hashes, peer=self)

    def loop_body(self):
        try:
            send_size = self._process_send()
            recv_size = self._process_recv()
        except IOError:
            self.stop()
            return
        # pause
        if not (send_size or recv_size):
            time.sleep(0.01)
<commit_msg>handle old protocol Hello gracefully<commit_after>import time
import Queue
import socket
import logging

import signals
from stoppable import StoppableLoopThread
from packeter import packeter
from utils import big_endian_to_int as idec
from utils import recursive_int_to_big_endian
import rlp
import blocks

# Maximum number of send hashes GetChain will accept
MAX_GET_CHAIN_ACCEPT_HASHES = 2048
# Maximum number of hashes GetChain will ever send
MAX_GET_CHAIN_SEND_HASHES = 2048
# Maximum number of blocks GetChain will ever ask for
MAX_GET_CHAIN_ASK_BLOCKS = 512
# Maximum number of requested blocks GetChain will accept
MAX_GET_CHAIN_REQUEST_BLOCKS = 512
# Maximum number of blocks Blocks will ever send
MAX_BLOCKS_SEND = MAX_GET_CHAIN_REQUEST_BLOCKS
# Maximum number of blocks Blocks will ever accept
MAX_BLOCKS_ACCEPTED = MAX_BLOCKS_SEND

logger = logging.getLogger(__name__)

class Peer(StoppableLoopThread):

    def __init__(self, connection, ip, port):
        super(Peer, self).__init__()
        self._connection = connection

        assert ip.count('.') == 3
        self.ip = ip
        # None if peer was created in response to external connect
        self.port = port
        self.client_version = ''
        self.node_id = ''
        self.capabilities = []  # [('eth',40) , ('shh',12)]

        self.hello_received = False
        self.hello_sent = False
        self.last_valid_packet_received = time.time()
        self.last_asked_for_peers = 0
        self.last_pinged = 0
        self.status_received = False
        self.status_sent = False
        self.status_total_difficulty = None
        self.status_head_hash = None

        self.recv_buffer = ''
        self.response_queue = Queue.Queue()

    def __repr__(self):
        return "<Peer(%s:%r)>" % (self.ip, self.port)

    def __str__(self):
        return "[{0}: {1}]".format(self.ip, self.port)

    def connection(self):
        if self.stopped():
            raise IOError("Connection was stopped")
        else:
            return self._connection

    def stop(self):
        super(Peer, self).stop()

        # shut down
        try:
            self._connection.shutdown(socket.SHUT_RDWR)
        except socket.error as e:
            logger.debug("shutting down failed %r '%s'", self, e)
        self._connection.close()

    def send_packet(self, response):
        logger.debug('sending %r >>> %s', self, packeter.packet_cmd(response))
        self.response_queue.put(response)

    def _process_send(self):
        '''
        :return: size of processed data
        '''
        # send packet
        try:
            packet = self.response_queue.get(block=False)
        except Queue.Empty:
            return 0
        try:
            self.connection().sendall(packet)
            return len(packet)
        except socket.error as e:
            logger.debug('%r: send packet failed, %s', self, e)
            self.stop()
            return 0

    def _process_recv(self):
        '''
        :return: size of processed data
        '''
        # receive complete message
        processed_length = 0
        while True:
            try:
                # print 'receiving'
                self.recv_buffer += self.connection().recv(2048)
            except socket.error:  # Timeout
                # print 'timeout'
                break
            # check if we have a complete packet
            length = len(self.recv_buffer)
            # length > packet_header and length > expected packet size
            while len(self.recv_buffer) >= 8 and len(self.recv_buffer) >= packeter.packet_size(self.recv_buffer):
                processed_length += packeter.packet_size(self.recv_buffer)
                self._process_recv_buffer()

        return processed_length

    def _process_recv_buffer(self):
        try:
            cmd, data, self.recv_buffer = packeter.load_cmd(self.recv_buffer)
        except Exception as e:
            self.recv_buffer = ''
            logger.warn(e)
            return self.send_Disconnect(reason='Bad protocol')

        # good peer
        self.last_valid_packet_received = time.time()
        logger.debug('receive %r <<< %s (%d)', self, cmd, len(data))
        func_name = "_recv_{0}".format(cmd)
        if not hasattr(self, func_name):
            logger.warn('unknown cmd "%s"', cmd)
            return
        getattr(self, func_name)(data)

    # Handshake
    def has_ethereum_capabilities(self):
        for p, pv in self.capabilities:
            if p == 'eth' and pv == packeter.ETHEREUM_PROTOCOL_VERSION:
                return True

    def send_Hello(self):
        logger.debug('%r sending Hello', self)
        self.send_packet(packeter.dump_Hello())
        self.hello_sent = True

    def _recv_Hello(self, data):
        # 0x01 Hello: [0x01: P, protocolVersion: P, clientVersion: B, [cap0: B, cap1: B, ...], listenPort: P, id: B_64]
        _decode = (idec, str, list, idec, str)
        try:
            data = [_decode[i](x) for i, x in enumerate(data)]
            network_protocol_version, client_version = data[0], data[1]
            capabilities, listen_port, node_id = data[2], data[3], data[4]
            self.capabilities = [(p,ord(v)) for p, v in capabilities]
        except (IndexError, ValueError) as e:
            logger.debug('%r could not decode Hello %s', self, e)
            return self.send_Disconnect(reason='Incompatible network protocols')

        logger.debug('%r received Hello PROTOCOL:%r NODE_ID:%r CLIENT_VERSION:%r CAPABILITIES:%r',
                     self, network_protocol_version, node_id.encode('hex')[:8], client_version, self.capabilities)

        if network_protocol_version != packeter.NETWORK_PROTOCOL_VERSION:
            logger.debug('%r Incompatible network protocols, expected %r, received %r',
                         self, packeter.NETWORK_PROTOCOL_VERSION, network_protocol_version)

            return self.send_Disconnect(reason='Incompatible network protocols')

        self.hello_received = True
        self.client_version = client_version
        self.node_id = node_id
        self.port = listen_port  # replace connection port with listen port

        if not self.hello_sent:
            self.send_Hello()
        signals.peer_handshake_success.send(sender=Peer, peer=self)

# Status

    def send_Status(self, head_hash, head_total_difficulty, genesis_hash):
        logger.debug('sending status TD:%d HEAD:%r GENESIS:%r',
                     head_total_difficulty, head_hash.encode('hex'), genesis_hash.encode('hex'))

        self.send_packet(packeter.dump_Status(head_total_difficulty, head_hash, genesis_hash))
        self.status_sent = True

    def _recv_Status(self, data):
        # [0x10: P, protocolVersion: P, networkID: P, totalDifficulty: P, latestHash: B_32, genesisHash: B_32]
        # check compatibility
        try:
            ethereum_protocol_version, network_id = idec(data[0]), idec(data[1])
            total_difficulty, head_hash, genesis_hash = idec(data[2]), data[3], data[4]
        except IndexError:
            return self.send_Disconnect(reason='Incompatible network protocols')

        logger.debug('%r, received Status ETHPROTOCOL:%r TD:%d HEAD:%r GENESIS:%r',
                     self, ethereum_protocol_version, total_difficulty,
                     head_hash.encode('hex'), genesis_hash.encode('hex'))

        if ethereum_protocol_version != packeter.ETHEREUM_PROTOCOL_VERSION:
            return self.send_Disconnect(reason='Incompatible network protocols')

        if network_id != packeter.NETWORK_ID:
            return self.send_Disconnect(reason='Wrong genesis block')

        if genesis_hash != blocks.genesis().hash:
            return self.send_Disconnect(reason='Wrong genesis block')

        self.status_received = True
        self.status_head_hash = head_hash
        self.status_total_difficulty = total_difficulty
        signals.peer_status_received.send(sender=Peer, peer=self)

# ping pong

    def send_Ping(self):
        self.send_packet(packeter.dump_Ping())
        self.last_pinged = time.time()

    def _recv_Ping(self, data):
        self.send_Pong()

    def send_Pong(self):
        self.send_packet(packeter.dump_Pong())

    def _recv_Pong(self, data):
        pass

# disconnects
    reasons_to_forget = ('Bad protocol',
                         'Incompatible network protocols',
                         'Wrong genesis block')

    def send_Disconnect(self, reason=None):
        logger.info('%r sending disconnect: %r', self, reason)
        self.send_packet(packeter.dump_Disconnect(reason=reason))
        # end connection
        time.sleep(2)
        forget = reason in self.reasons_to_forget
        signals.peer_disconnect_requested.send(Peer, peer=self, forget=forget)

    def _recv_Disconnect(self, data):
        if len(data):
            reason = packeter.disconnect_reasons_map_by_id[idec(data[0])]
            logger.info('%r received disconnect: %r', self, reason)
            forget = reason in self.reasons_to_forget
        else:
            forget = None
            logger.info('%r received disconnect: w/o reason', self)
        signals.peer_disconnect_requested.send(sender=Peer, peer=self, forget=forget)

# peers

    def send_GetPeers(self):
        self.send_packet(packeter.dump_GetPeers())

    def _recv_GetPeers(self, data):
        signals.getpeers_received.send(sender=Peer, peer=self)

    def send_Peers(self, peers):
        if peers:
            packet = packeter.dump_Peers(peers)
            self.send_packet(packet)

    def _recv_Peers(self, data):
        addresses = []
        for ip, port, pid in data:
            assert len(ip) == 4
            ip = '.'.join(str(ord(b)) for b in ip)
            port = idec(port)
            logger.debug('received peer address: {0}:{1}'.format(ip, port))
            addresses.append([ip, port, pid])
        signals.peer_addresses_received.send(sender=Peer, addresses=addresses)

# transactions

    def send_Transactions(self, transactions):
        self.send_packet(packeter.dump_Transactions(transactions))

    def _recv_Transactions(self, data):
        logger.debug('received transactions #%d', len(data))
        signals.remote_transactions_received.send(sender=Peer, transactions=data, peer=self)

# blocks

    def send_Blocks(self, blocks):
        assert len(blocks) <= MAX_BLOCKS_SEND
        self.send_packet(packeter.dump_Blocks(blocks))

    def _recv_Blocks(self, data):
        # open('raw_remote_blocks_hex.txt', 'a').write(rlp.encode(data).encode('hex') + '\n') # LOG line
        transient_blocks = [blocks.TransientBlock(rlp.encode(b)) for b in data]  # FIXME
        if len(transient_blocks) > MAX_BLOCKS_ACCEPTED:
            logger.warn('Peer sending too many blocks %d', len(transient_blocks))
        signals.remote_blocks_received.send(sender=Peer, peer=self, transient_blocks=transient_blocks)

    def send_GetBlocks(self, block_hashes):
        self.send_packet(packeter.dump_GetBlocks(block_hashes))

    def _recv_GetBlocks(self, block_hashes):
        signals.get_blocks_received.send(
            sender=Peer, block_hashes=block_hashes, peer=self)

# new blocks
    def send_NewBlock(self, block):
        self.send_packet(packeter.dump_NewBlock(block))

    def _recv_NewBlock(self, data):
        logger.debug('NewBlock: %r', rlp.encode(data).encode('hex'))
        total_difficulty = idec(data[1])
        transient_block = blocks.TransientBlock(rlp.encode(data[0]))
        signals.new_block_received.send(
            sender=Peer, peer=self, block=transient_block)

# block hashes
    def send_GetBlockHashes(self, block_hash, max_blocks):
        self.send_packet(packeter.dump_GetBlockHashes(block_hash, max_blocks))

    def _recv_GetBlockHashes(self, data):
        block_hash, count = data[0], idec(data[1])
        signals.get_block_hashes_received.send(sender=Peer, block_hash=block_hash, count=count, peer=self)

    def send_BlockHashes(self, block_hashes):
        self.send_packet(packeter.dump_BlockHashes(block_hashes))

    def _recv_BlockHashes(self, block_hashes):
        signals.remote_block_hashes_received.send(sender=Peer, block_hashes=block_hashes, peer=self)

    def loop_body(self):
        try:
            send_size = self._process_send()
            recv_size = self._process_recv()
        except IOError:
            self.stop()
            return
        # pause
        if not (send_size or recv_size):
            time.sleep(0.01)
<|endoftext|>


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

"""
Contains the base Flask application setup.  This module is also the
location that sets up the initial database connection.  This is done so that
both developers and running unittests can intercept the configuration and
add their own.  After setting up the application :func:`pyfarm.run.run`
will handle the execution of the Flask application
"""

import os
import uuid
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

from pyfarm import dist
from pyfarm.error import SubKeyError, PreferencesError
from pyfarm.config.database import DBConfig

app = Flask("PyFarm",
            static_folder=os.path.join(dist.location, "pyfarm-files", "static"),
            static_url_path="")
dbconfig = DBConfig()

# iterate over configuration names we should expect to find
for config_name in dbconfig.get("config_order"):
    try:
        dburi = dbconfig.url(config_name)
    except SubKeyError:
        continue
    else:
        break
else:
    # there's something wrong with the setup if we reach this point
    raise PreferencesError("failed to find any database configurations")

app.config["SQLALCHEMY_DATABASE_URI"] = dburi
app.secret_key = str(uuid.uuid4())  # TODO: this needs a config or extern lookup

db = SQLAlchemy(app)
<commit_msg>better dburl setup<commit_after># No shebang line, this module is meant to be imported
#
# Copyright 2013 Oliver Palmer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Contains the base Flask application setup.  This module is also the
location that sets up the initial database connection.  This is done so that
both developers and running unittests can intercept the configuration and
add their own.  After setting up the application :func:`pyfarm.run.run`
will handle the execution of the Flask application
"""

import os
import uuid
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

from pyfarm import dist
from pyfarm.error import SubKeyError, PreferencesError
from pyfarm.config.database import DBConfig

app = Flask("PyFarm",
            static_folder=os.path.join(dist.location, "pyfarm-files", "static"),
            static_url_path="")

app.config["SQLALCHEMY_DATABASE_URI"] = DBConfig().url()
app.secret_key = str(uuid.uuid4())  # TODO: this needs a config or extern lookup

db = SQLAlchemy(app)
<|endoftext|>


<commit_before># pyinfra
# File: pyinfra/version.py
# Desc: version file

__version__ = '0.2dev1'
<commit_msg>Dev2 (attempting to convince pypi to render the long description properly).<commit_after># pyinfra
# File: pyinfra/version.py
# Desc: version file

__version__ = '0.2dev2'
<|endoftext|>


<commit_before>import constants
from . import register_message_class
from . import Message
from . import UnsignedInt
from . import UnsignedIntMask
from . import Timestamp
from . import Bitfield
from . import CompletionCode
from . import Conditional
from . import Optional
from . import RemainingBytes
from picmg import PicmgIdentifier

@register_message_class
class GetTargetUpgradeCapabilitiesReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class GetTargetUpgradeCapabilitiesRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('hpm_1_version', 1),
            Bitfield('capabilities', 1,
                Bitfield.Bit('firmware_upgrade_undesirable', 1),
                Bitfield.Bit('automatic_rollback_overriden', 1),
                Bitfield.Bit('ipmc_degraded_during_upgrade', 1),
                Bitfield.Bit('deferred_activation', 1),
                Bitfield.Bit('services_affected_by_upgrade', 1),
                Bitfield.Bit('manual_rollback', 1),
                Bitfield.Bit('automatic_rollback', 1),
                Bitfield.Bit('selftest', 1),
            ),
            Bitfield('timeout', 4,
                Bitfield.Bit('upgrade', 8),
                Bitfield.Bit('selftest', 8),
                Bitfield.Bit('rollback', 8),
                Bitfield.Bit('inaccessibility', 8),
            ),
            UnsignedInt('component_present', 1),
    )

@register_message_class
class GetComponentPropertiesReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('id', 1),
            UnsignedInt('selector', 1),
    )

@register_message_class
class GetComponentPropertiesRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            RemainingBytes('data'),
    )

@register_message_class
class AbortFirmwareUpgradeReq(Message):
    __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class AbortFirmwareUpgradeRsp(Message):
    __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class InitiateUpgradeActionReq(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('components', 1),
            UnsignedInt('action', 1),
    )

@register_message_class
class InitiateUpgradeActionRsp(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class UploadFirmwareBlockReq(Message):
    __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            RemainingBytes('data'),
    )

@register_message_class
class UploadFirmwareBlockRsp(Message):
    __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            Optional(UnsignedInt('section_offset', 4)),
            Optional(UnsignedInt('section_length', 4)),
    )

@register_message_class
class FinishFirmwareUploadReq(Message):
    __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('component_id', 1),
            UnsignedInt('image_length', 4),
    )

@register_message_class
class FinishFirmwareUploadRsp(Message):
    __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class GetUpgradeStatusReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class GetUpgradeStatusRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('command_in_progress', 1),
            Optional(UnsignedInt('completion_estimate', 1)),
    )

@register_message_class
class ActivateFirmwareReq(Message):
    __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            Optional(UnsignedInt('rollback_override_policy', 1)),
    )

@register_message_class
class ActivateFirmwareRsp(Message):
    __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class QuerySelftestResultsReq(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class QuerySelftestResultsRsp(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('selftest_result_1', 1),
            UnsignedInt('selftest_result_2', 1),
    )

@register_message_class
class QueryRollbackStatusReq(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class QueryRollbackStatusRsp(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('rollback_status', 1),
            Optional(UnsignedInt('completion_estimate', 1)),
    )

@register_message_class
class InitiateManualRollbackReq(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class InitiateManualRollbackRsp(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )
<commit_msg>msgs: hpm: add missing message parameters<commit_after>import constants
from . import register_message_class
from . import Message
from . import UnsignedInt
from . import UnsignedIntMask
from . import Timestamp
from . import Bitfield
from . import CompletionCode
from . import Conditional
from . import Optional
from . import RemainingBytes
from picmg import PicmgIdentifier

@register_message_class
class GetTargetUpgradeCapabilitiesReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class GetTargetUpgradeCapabilitiesRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('hpm_1_version', 1),
            Bitfield('capabilities', 1,
                Bitfield.Bit('firmware_upgrade_undesirable', 1),
                Bitfield.Bit('automatic_rollback_overriden', 1),
                Bitfield.Bit('ipmc_degraded_during_upgrade', 1),
                Bitfield.Bit('deferred_activation', 1),
                Bitfield.Bit('services_affected_by_upgrade', 1),
                Bitfield.Bit('manual_rollback', 1),
                Bitfield.Bit('automatic_rollback', 1),
                Bitfield.Bit('selftest', 1),
            ),
            Bitfield('timeout', 4,
                Bitfield.Bit('upgrade', 8),
                Bitfield.Bit('selftest', 8),
                Bitfield.Bit('rollback', 8),
                Bitfield.Bit('inaccessibility', 8),
            ),
            UnsignedInt('component_present', 1),
    )

@register_message_class
class GetComponentPropertiesReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('id', 1),
            UnsignedInt('selector', 1),
    )

@register_message_class
class GetComponentPropertiesRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            RemainingBytes('data'),
    )

@register_message_class
class AbortFirmwareUpgradeReq(Message):
    __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class AbortFirmwareUpgradeRsp(Message):
    __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class InitiateUpgradeActionReq(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('components', 1),
            UnsignedInt('action', 1),
    )

@register_message_class
class InitiateUpgradeActionRsp(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class UploadFirmwareBlockReq(Message):
    __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('number', 1),
            RemainingBytes('data'),
    )

@register_message_class
class UploadFirmwareBlockRsp(Message):
    __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            Optional(UnsignedInt('section_offset', 4)),
            Optional(UnsignedInt('section_length', 4)),
    )

@register_message_class
class FinishFirmwareUploadReq(Message):
    __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            UnsignedInt('component_id', 1),
            UnsignedInt('image_length', 4),
    )

@register_message_class
class FinishFirmwareUploadRsp(Message):
    __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class GetUpgradeStatusReq(Message):
    __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class GetUpgradeStatusRsp(Message):
    __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('command_in_progress', 1),
            UnsignedInt('last_completion_code', 1),
            Optional(UnsignedInt('completion_estimate', 1)),
    )

@register_message_class
class ActivateFirmwareReq(Message):
    __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
            Optional(UnsignedInt('rollback_override_policy', 1)),
    )

@register_message_class
class ActivateFirmwareRsp(Message):
    __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )

@register_message_class
class QuerySelftestResultsReq(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class QuerySelftestResultsRsp(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('selftest_result_1', 1),
            UnsignedInt('selftest_result_2', 1),
    )

@register_message_class
class QueryRollbackStatusReq(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class QueryRollbackStatusRsp(Message):
    __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
            UnsignedInt('rollback_status', 1),
            Optional(UnsignedInt('completion_estimate', 1)),
    )

@register_message_class
class InitiateManualRollbackReq(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK
    __netfn__ = constants.NETFN_GROUP_EXTENSION
    __default_lun__ = 0
    __fields__ = (
            PicmgIdentifier(),
    )

@register_message_class
class InitiateManualRollbackRsp(Message):
    __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK
    __netfn__ = constants.NETFN_GROUP_EXTENSION | 1
    __default_lun__ = 0
    __fields__ = (
            CompletionCode(),
            PicmgIdentifier(),
    )
<|endoftext|>


<commit_before>from sys import version_info
if version_info[0:2] > (2, 2):
    from unicodedata import normalize
else:
    normalize = None

from rdflib.Identifier import Identifier
from rdflib.exceptions import Error

class Literal(Identifier):
    """

    http://www.w3.org/TR/rdf-concepts/#section-Graph-Literal
    """

    __slots__ = ("language", "datatype")

    def __new__(cls, value, lang=None, datatype=None):
        #if normalize and value:
        #    if value != normalize("NFC", value):
        #        raise Error("value must be in NFC normalized form.")
        try:
            inst = unicode.__new__(cls,value)
        except UnicodeDecodeError:
            inst = unicode.__new__(cls,value,'utf-8')

        if datatype:
            lang = None
        inst.language = lang
        inst.datatype = datatype
        return inst

    def __reduce__(self):
        return (Literal, (unicode(self), self.language, self.datatype),)

#
#    def __getnewargs__(self):
#        return (unicode(self), self.language, self.datatype)

    def __getstate__(self):
        return (None, dict(language=self.language, datatype=self.datatype))

    def __setstate__(self, arg):
        _, d = arg
        self.language = d["language"]
        self.datatype = d["datatype"]

    def __add__(self, val):
        s = super(Literal, self).__add__(val)
        return Literal(s, self.language, self.datatype)

    def __eq__(self, other):
        if other==None:
            return False
        elif isinstance(other, Literal):
            result = self.__cmp__(other)==False
            if result==True:
                if self.datatype == None or self.datatype == '' :
                    if not(other.datatype == None or other.datatype == '') :
                        return False
                else:
                    if other.datatype == None or other.datatype == '' :
                        return False
                    elif self.datatype != other.datatype :
                        return False
                if self.language!=other.language:
                    return False
                return True
            else:
                return result
        elif isinstance(other, Identifier):
            return False
        else:
            return unicode(self)==other

    def n3(self):
        language = self.language
        datatype = self.datatype
        encoded = self.encode('unicode-escape').replace('\\', '\\\\').replace('"','\\"')
        if language:
            if datatype:
                return '"%s"@%s^^<%s>' % (encoded, language, datatype)
            else:
                return '"%s"@%s' % (encoded, language)
        else:
            if datatype:
                return '"%s"^^<%s>' % (encoded, datatype)
            else:
                return '"%s"' % encoded

    def __repr__(self):
        return """<Literal language=%s datatype=%s value=%s>""" % (repr(self.language), repr(self.datatype), unicode(self))
<commit_msg>added support for Literal casting to and from python datatypes (in the constructor and in a toPython function)<commit_after>from sys import version_info
if version_info[0:2] > (2, 2):
    from unicodedata import normalize
else:
    normalize = None

from rdflib.Identifier import Identifier
from rdflib.exceptions import Error
from datetime import date,time,datetime
import base64

XSD_NS = u'http://www.w3.org/2001/XMLSchema#'

#Casts a python datatype to a tuple of the lexical value and a datatype URI (or None)
def castPythonToLiteral(obj):
    for pType,(castFunc,dType) in PythonToXSD.items():
        if isinstance(obj,pType):
            if castFunc:
                return castFunc(obj),dType
            elif dType:
                return obj,dType
            else:
                return obj,None

#Mappings from Python types to XSD datatypes and back (burrowed from sparta)
PythonToXSD = {
    basestring : (None,None),
    float      : (None,XSD_NS+u'float'),
    int        : (None,XSD_NS+u'int'),
    long       : (None,XSD_NS+u'long'),
    bool       : (None,XSD_NS+u'boolean'),
    date       : (lambda i:i.isoformat(),XSD_NS+u'date'),
    time       : (lambda i:i.isoformat(),XSD_NS+u'time'),
    datetime   : (lambda i:i.isoformat(),XSD_NS+u'dateTime'),
}

XSDToPython = {
    XSD_NS+u'string'             : (None,None),
    XSD_NS+u'normalizedString'   : (None,None),
    XSD_NS+u'token'              : (None,None),
    XSD_NS+u'language'           : (None,None),
    XSD_NS+u'boolean'            : (None, lambda i:i.lower() in ['1','true']),
    XSD_NS+u'decimal'            : (float,None),
    XSD_NS+u'integer'            : (long ,None),
    XSD_NS+u'nonPositiveInteger' : (int,None),
    XSD_NS+u'long'               : (long,None),
    XSD_NS+u'nonNegativeInteger' : (int, None),
    XSD_NS+u'negativeInteger'    : (int, None),
    XSD_NS+u'int'                : (int, None),
    XSD_NS+u'unsignedLong'       : (long, None),
    XSD_NS+u'positiveInteger'    : (int, None),
    XSD_NS+u'short'              : (int, None),
    XSD_NS+u'unsignedInt'        : (long, None),
    XSD_NS+u'byte'               : (int, None),
    XSD_NS+u'unsignedShort'      : (int, None),
    XSD_NS+u'unsignedByte'       : (int, None),
    XSD_NS+u'float'              : (float, None),
    XSD_NS+u'double'             : (float, None),
    XSD_NS+u'base64Binary'       : (base64.decodestring, None),
    XSD_NS+u'anyURI'             : (None,None),
}

class Literal(Identifier):
    """

    http://www.w3.org/TR/rdf-concepts/#section-Graph-Literal
    """

    __slots__ = ("language", "datatype")

    def __new__(cls, value, lang=None, datatype=None):
        #if normalize and value:
        #    if value != normalize("NFC", value):
        #        raise Error("value must be in NFC normalized form.")
        if datatype:
            lang = None
        else:
            value,datatype = castPythonToLiteral(value)
            if datatype:
                lang = None
        try:
            inst = unicode.__new__(cls,value)
        except UnicodeDecodeError:
            inst = unicode.__new__(cls,value,'utf-8')

        inst.language = lang
        inst.datatype = datatype
        return inst

    def __reduce__(self):
        return (Literal, (unicode(self), self.language, self.datatype),)

#
#    def __getnewargs__(self):
#        return (unicode(self), self.language, self.datatype)

    def __getstate__(self):
        return (None, dict(language=self.language, datatype=self.datatype))

    def __setstate__(self, arg):
        _, d = arg
        self.language = d["language"]
        self.datatype = d["datatype"]

    def __add__(self, val):
        s = super(Literal, self).__add__(val)
        return Literal(s, self.language, self.datatype)

    def __eq__(self, other):
        if other==None:
            return False
        elif isinstance(other, Literal):
            result = self.__cmp__(other)==False
            if result==True:
                if self.datatype == None or self.datatype == '' :
                    if not(other.datatype == None or other.datatype == '') :
                        return False
                else:
                    if other.datatype == None or other.datatype == '' :
                        return False
                    elif self.datatype != other.datatype :
                        return False
                if self.language!=other.language:
                    return False
                return True
            else:
                return result
        elif isinstance(other, Identifier):
            return False
        else:
            return unicode(self)==other

    def n3(self):
        language = self.language
        datatype = self.datatype
        encoded = self.encode('unicode-escape').replace('\\', '\\\\').replace('"','\\"')
        if language:
            if datatype:
                return '"%s"@%s^^<%s>' % (encoded, language, datatype)
            else:
                return '"%s"@%s' % (encoded, language)
        else:
            if datatype:
                return '"%s"^^<%s>' % (encoded, datatype)
            else:
                return '"%s"' % encoded

    def __repr__(self):
        klass,convFunc = XSDToPython.get(self.datatype,(None,None))
        if klass:
            return "%s(%s)"%(klass.__name__,str(self))
        else:
            return """<Literal language=%s datatype=%s value=%s>""" % (repr(self.language), repr(self.datatype), unicode(self))

    def toPython(self):
        """
        Returns an appropriate python datatype derived from this RDF Literal
        """
        klass,convFunc = XSDToPython.get(self.datatype,(None,None))
        rt = self
        if convFunc:
            rt = convFunc(rt)
        if klass:
            rt = klass(rt)
        return rt<|endoftext|>


<commit_before>class W_Object(object):
    def __init__(self):
        self.n_val = 0
        self.s_val = ''

    def eq(self, w_other):
        raise NotImplementedError('eq not supported by this class')

    def neq(self, w_other):
        raise NotImplementedError('neq not supported by this class')

    def gt(self, other):
        raise NotImplementedError('gt not supported by this class')

    def lt(self, other):
        raise NotImplementedError('lt not supported by this class')

    def ge(self, other):
        raise NotImplementedError('ge not supported by this class')

    def le(self, other):
        raise NotImplementedError('le not supported by this class')

    def to_str(self):
        raise NotImplementedError('to_str not supported by this class')

    def clone(self):
        raise NotImplementedError('to_str not supported by this class')

class W_Num(W_Object):
    def __init__(self, val):
        self.n_val = val

    def getval(self):
        return self.n_val

    def eq(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val == w_other.getval()

    def neq(self, w_other):
        return not self.eq(w_other)

    def gt(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val > w_other.n_val

    def lt(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val < w_other.n_val

    def le(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val <= w_other.n_val

    def ge(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val >= w_other.n_val

    def to_str(self):
        return str(self.n_val)

    def clone(self):
        return W_Num(self.n_val)

class W_Str(W_Object):
    def __init__(self, val):
        self.s_val = val

    def getval(self):
        return self.s_val

    def eq(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val == w_other.getval()

    def neq(self, w_other):
        return not self.eq(w_other)

    def gt(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val > w_other.s_val

    def lt(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val < w_other.s_val

    def le(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val <= w_other.s_val

    def ge(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val >= w_other.s_val

    def to_str(self):
        return str(self.s_val)

    def clone(self):
        return W_Str(self.s_val)

class W_Func(W_Object):
    def __init__(self, val):
        self.f_val = val

    def getval(self):
        return self.f_val

    def clone(self):
        return W_Func(self.f_val)

class W_Pri(W_Num):
    def __init__(self, val):
        assert val in (0, 1, 2)
        self.n_val = val

    def to_str(self):
        if self.n_val == 0:
            return 'nil'
        elif self.n_val == 1:
            return 'false'
        else:
            return 'true'

    def clone(self):
        return W_Pri(self.n_val)
<commit_msg>Add W_Table<commit_after>class W_Object(object):
    def __init__(self):
        self.n_val = 0
        self.s_val = ''
        self.content = {}

    def eq(self, w_other):
        raise NotImplementedError('eq not supported by this class')

    def neq(self, w_other):
        raise NotImplementedError('neq not supported by this class')

    def gt(self, other):
        raise NotImplementedError('gt not supported by this class')

    def lt(self, other):
        raise NotImplementedError('lt not supported by this class')

    def ge(self, other):
        raise NotImplementedError('ge not supported by this class')

    def le(self, other):
        raise NotImplementedError('le not supported by this class')

    def to_str(self):
        raise NotImplementedError('to_str not supported by this class')

    def clone(self):
        raise NotImplementedError('to_str not supported by this class')

    def get_val(self, key):
        raise NotImplementedError('to_str not supported by this class')

class W_Num(W_Object):
    def __init__(self, val):
        self.n_val = val

    def getval(self):
        return self.n_val

    def eq(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val == w_other.getval()

    def neq(self, w_other):
        return not self.eq(w_other)

    def gt(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val > w_other.n_val

    def lt(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val < w_other.n_val

    def le(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val <= w_other.n_val

    def ge(self, w_other):
        assert isinstance(w_other, W_Num)
        return self.n_val >= w_other.n_val

    def to_str(self):
        return str(self.n_val)

    def clone(self):
        return W_Num(self.n_val)

class W_Str(W_Object):
    def __init__(self, val):
        self.s_val = val

    def getval(self):
        return self.s_val

    def eq(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val == w_other.getval()

    def neq(self, w_other):
        return not self.eq(w_other)

    def gt(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val > w_other.s_val

    def lt(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val < w_other.s_val

    def le(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val <= w_other.s_val

    def ge(self, w_other):
        assert isinstance(w_other, W_Str)
        return self.s_val >= w_other.s_val

    def to_str(self):
        return str(self.s_val)

    def clone(self):
        return W_Str(self.s_val)

class W_Func(W_Object):
    def __init__(self, val):
        self.f_val = val

    def getval(self):
        return self.f_val

    def clone(self):
        return W_Func(self.f_val)

class W_Pri(W_Num):
    def __init__(self, val):
        assert val in (0, 1, 2)
        self.n_val = val

    def to_str(self):
        if self.n_val == 0:
            return 'nil'
        elif self.n_val == 1:
            return 'false'
        else:
            return 'true'

    def clone(self):
        return W_Pri(self.n_val)

class W_Table(W_Object):
    def __init__(self):
        self.content = {}

    def get_val(self, key):
        w_v = self.content[key]
        assert isinstance(w_v, W_Object)
        return w_v

    def set_val(self, key, val):
        self.content[key] = val
<|endoftext|>


<commit_before>from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify
from django_enumfield import enum

from null_reality.models import NullCheckerModel
from null_reality.fields import NullableCharField, NullableTextField

class Recipe(NullCheckerModel):
    """
    Stores recipes that users can find on the site.

    :field title: CharField, max_length=150, unique=True
    :field slug: SlugField, unique=True, defaults to slugified version of title
    :field short_description: CharField, max_length=200
    :field image: ImageField, uploads to 'recipes/images', optional
    :field thumbnail: ImageField, uploads to 'recipes/thumbs', optional
    :field ingredients: TextField
    :field instructions: TextField
    :field featured: BooleanField, defaults to False
    :field is_public: BooleanField, defaults to True
    :field added_by: ForeignKey to User
    :field date_added: DateTimeField, auto_now_add
    """
    title = NullableCharField(max_length=150, unique=True)
    slug = models.SlugField(unique=True, blank=True, help_text="URL slug that " +
                            "will be used for this recipe's address. If you " +
                            "leave this field blank, it will default to a " +
                            "slugified version of the title.")
    short_description = NullableCharField(max_length=200)
    tags = models.ManyToManyField(RecipeTag, blank=True, null=True)
    image = models.ImageField(upload_to='recipes/images', blank=True, null=True,
                              help_text="Display image for the recipe. The " +
                              "ideal image size is 200x200px.")
    thumbnail = models.ImageField(upload_to='recipes/thumbs', blank=True, null=True,
                                  help_text="Smaller image to use for the " +
                                  "recipe. Ideal image size is 60x60px")
    ingredients = NullableTextField(help_text="Ingredients (with measurements) " +
                                   "for the recipe, one ingredient per line.")
    instructions = NullableTextField(help_text="Instructions for preparing the " +
                                    "recipe.")
    featured = models.BooleanField(default=False, help_text="If true, this " +
                                   "recipe will show up under the 'Featured' " +
                                   "section of the home page")
    is_public = models.BooleanField(default=True, help_text="If false, this " +
                                    "recipe will not show up in public searches")
    added_by = models.ForeignKey(User, help_text="User who created this recipe.")
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('title', 'id')

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Recipe, self).save(*args, **kwargs)

    def __repr__(self):
        return "<Recipe: %s (by %s)>" % (self.title, self.added_by)

    def __unicode__(self):
        return unicode(self.title)

class TagType(enum.Enum):
    """
    Classifications for RecipeTags.

    Types:
        OTHER: default tag, an easy way to identify new tags created by users
        MEAL: a particular kind of eating situation (breakfast, lunch, finger
            food)
        INGREDIENT: a classification based on the types of ingredients in a
            recipe (vegan, low-carb, gluten-free)
            passover/pesach, finger food)
    """
    OTHER = 0
    INGREDIENT = 1
    MEAL = 2

class RecipeTag(NullCheckerModel):
    """
    A way for users to classify recipes.

    :field tag: CharField, max length=30, unique
    :field type: EnumField using TagType
    :field is_public: BooleanField, defaults to True
    :field added_by: ForeignKey to User, nullable
    :field date_added: DateTimeField, auto_now_add
    """
    tag = NullableCharField(max_length=30, unique=True)
    type = enum.EnumField(TagType)
    is_public = models.BooleanField(default=True)
    added_by = models.ForeignKey(User, blank=True, null=True)
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('type', 'tag')

    def save(self, *args, **kwargs):
        self.tag = self.tag.lower()
        super(RecipeTag, self).save(*args, **kwargs)

    # TODO: tags stored as lower case
    # TODO: repr and unicode
    # TODO: tests for init, repr, and unicode
    # TODO: tests for save -- make sure it catches uniqueness issues
<commit_msg>[#2] RecipeTag repr and unicode<commit_after>from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify
from django_enumfield import enum

from null_reality.models import NullCheckerModel
from null_reality.fields import NullableCharField, NullableTextField

class Recipe(NullCheckerModel):
    """
    Stores recipes that users can find on the site.

    :field title: CharField, max_length=150, unique=True
    :field slug: SlugField, unique=True, defaults to slugified version of title
    :field short_description: CharField, max_length=200
    :field image: ImageField, uploads to 'recipes/images', optional
    :field thumbnail: ImageField, uploads to 'recipes/thumbs', optional
    :field ingredients: TextField
    :field instructions: TextField
    :field featured: BooleanField, defaults to False
    :field is_public: BooleanField, defaults to True
    :field added_by: ForeignKey to User
    :field date_added: DateTimeField, auto_now_add
    """
    title = NullableCharField(max_length=150, unique=True)
    slug = models.SlugField(unique=True, blank=True, help_text="URL slug that " +
                            "will be used for this recipe's address. If you " +
                            "leave this field blank, it will default to a " +
                            "slugified version of the title.")
    short_description = NullableCharField(max_length=200)
    tags = models.ManyToManyField(RecipeTag, blank=True, null=True)
    image = models.ImageField(upload_to='recipes/images', blank=True, null=True,
                              help_text="Display image for the recipe. The " +
                              "ideal image size is 200x200px.")
    thumbnail = models.ImageField(upload_to='recipes/thumbs', blank=True, null=True,
                                  help_text="Smaller image to use for the " +
                                  "recipe. Ideal image size is 60x60px")
    ingredients = NullableTextField(help_text="Ingredients (with measurements) " +
                                   "for the recipe, one ingredient per line.")
    instructions = NullableTextField(help_text="Instructions for preparing the " +
                                    "recipe.")
    featured = models.BooleanField(default=False, help_text="If true, this " +
                                   "recipe will show up under the 'Featured' " +
                                   "section of the home page")
    is_public = models.BooleanField(default=True, help_text="If false, this " +
                                    "recipe will not show up in public searches")
    added_by = models.ForeignKey(User, help_text="User who created this recipe.")
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('title', 'id')

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Recipe, self).save(*args, **kwargs)

    def __repr__(self):
        return "<Recipe: %s (by %s)>" % (self.title, self.added_by)

    def __unicode__(self):
        return unicode(self.title)

class TagType(enum.Enum):
    """
    Classifications for RecipeTags.

    Types:
        OTHER: default tag, an easy way to identify new tags created by users
        MEAL: a particular kind of eating situation (breakfast, lunch, finger
            food)
        INGREDIENT: a classification based on the types of ingredients in a
            recipe (vegan, low-carb, gluten-free)
            passover/pesach, finger food)
    """
    OTHER = 0
    INGREDIENT = 1
    MEAL = 2

class RecipeTag(NullCheckerModel):
    """
    A way for users to classify recipes.

    :field tag: CharField, max length=30, unique
    :field type: EnumField using TagType
    :field is_public: BooleanField, defaults to True
    :field added_by: ForeignKey to User, nullable
    :field date_added: DateTimeField, auto_now_add
    """
    tag = NullableCharField(max_length=30, unique=True)
    type = enum.EnumField(TagType)
    is_public = models.BooleanField(default=True)
    added_by = models.ForeignKey(User, blank=True, null=True)
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('type', 'tag')

    def save(self, *args, **kwargs):
        self.tag = self.tag.lower()
        super(RecipeTag, self).save(*args, **kwargs)

    def __repr__(self):
        return "<RecipeTag: %s>" % self.tag

    def __unicode__(self):
        return unicode(self.tag)
<|endoftext|>


<commit_before># coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

import re
import numpy as np
from pymatgen.core.structure import Molecule
from monty.io import zopen

"""
Module implementing an XYZ file object class.
"""

__author__ = "Shyue Ping Ong"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Shyue Ping Ong"
__email__ = "shyuep@gmail.com"
__date__ = "Apr 17, 2012"

class XYZ:
    """
    Basic class for importing and exporting Molecules or Structures in XYZ
    format.

    Args:
        mol: Input molecule or list of molecules

    .. note::
        Exporting periodic structures in the XYZ format will lose information
        about the periodicity. Essentially, only cartesian coordinates are
        written in this format and no information is retained about the
        lattice.
    """
    def __init__(self, mol, coord_precision=6):
        if isinstance(mol, Molecule) or not isinstance(mol, list):
            self._mols = [mol]
        else:
            self._mols = mol
        self.precision = coord_precision

    @property
    def molecule(self):
        """
        Returns molecule associated with this XYZ. In case multiple frame
        XYZ, returns the last frame.
        """
        return self._mols[-1]

    @property
    def all_molecules(self):
        """
        Returns all the frames of molecule associated with this XYZ.
        """
        return self._mols

    @staticmethod
    def _from_frame_string(contents):
        """
        Convert a single frame XYZ string to a molecule
        """
        lines = contents.split("\n")
        num_sites = int(lines[0])
        coords = []
        sp = []
        coord_patt = re.compile(
            r"(\w+)\s+([0-9\-\+\.eEdD]+)\s+([0-9\-\+\.eEdD]+)\s+([0-9\-\+\.eEdD]+)"
        )
        for i in range(2, 2 + num_sites):
            m = coord_patt.search(lines[i])
            if m:
                sp.append(m.group(1))  # this is 1-indexed
                # this is 0-indexed
                # in case of 0.0D+00 or 0.00d+01 old double precision writing
                # replace d or D by e for ten power exponent
                xyz = [val.lower().replace("d", "e") for val in m.groups()[1:4]]
                coords.append([float(val) for val in xyz])
        return Molecule(sp, coords)

    @staticmethod
    def from_string(contents, step_skip=1):
        """
        Creates XYZ object from a string.

        Args:
            contents: String representing an XYZ file.

        Returns:
            XYZ object
        """
        if contents[-1] != "\n":
            contents += "\n"
        white_space = r"[ \t\r\f\v]"
        natoms_line = white_space + r"*\d+" + white_space + r"*\n"
        comment_line = r"[^\n]*\n"
        coord_lines = r"(\s*\w+\s+[0-9\-\+\.eEdD]+\s+[0-9\-\+\.eEdD]+\s+[0-9\-\+\.eEdD]+\s*\n)+"
        frame_pattern_text = natoms_line + comment_line + coord_lines
        pat = re.compile(frame_pattern_text, re.MULTILINE)
        mols = []
        for i, xyz_match in enumerate(pat.finditer(contents)):
            xyz_text = xyz_match.group(0)
            if i % step_skip == 0:
                mols.append(XYZ._from_frame_string(xyz_text))
        return XYZ(mols)

    @staticmethod
    def from_file(filename, step_skip=1):
        """
        Creates XYZ object from a file.

        Args:
            filename: XYZ filename

        Returns:
            XYZ object
        """
        with zopen(filename, 'rt') as f:
            return XYZ.from_string(f.read(), step_skip)

    def _frame_str(self, frame_mol):
        output = [str(len(frame_mol)), frame_mol.composition.formula]
        fmtstr = "{{}} {{:.{0}f}} {{:.{0}f}} {{:.{0}f}}".format(self.precision)
        for site in frame_mol:
            output.append(fmtstr.format(site.specie, site.x, site.y, site.z))
        return "\n".join(output)

    def __str__(self):
        return "\n".join([self._frame_str(mol) for mol in self._mols])

    def write_file(self, filename):
        """
        Writes XYZ to file.

        Args:
            filename: File name of output file.
        """
        with zopen(filename, "wt") as f:
            f.write(self.__str__())
<commit_msg>Revert XYZ back to upstream.<commit_after># coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

"""
Module implementing an XYZ file object class.
"""

import re

from pymatgen.core.structure import Molecule
from monty.io import zopen

class XYZ:
    """
    Basic class for importing and exporting Molecules or Structures in XYZ
    format.

    .. note::
        Exporting periodic structures in the XYZ format will lose information
        about the periodicity. Essentially, only cartesian coordinates are
        written in this format and no information is retained about the
        lattice.
    """
    def __init__(self, mol: Molecule, coord_precision: int = 6):
        """
        Args:
            mol: Input molecule or list of molecules
            coord_precision: Precision to be used for coordinates.
        """
        if isinstance(mol, Molecule) or not isinstance(mol, list):
            self._mols = [mol]
        else:
            self._mols = mol
        self.precision = coord_precision

    @property
    def molecule(self) -> Molecule:
        """
        Returns molecule associated with this XYZ. In case multiple frame
        XYZ, returns the last frame.
        """
        return self._mols[-1]

    @property
    def all_molecules(self):
        """
        Returns all the frames of molecule associated with this XYZ.
        """
        return self._mols

    @staticmethod
    def _from_frame_string(contents):
        """
        Convert a single frame XYZ string to a molecule
        """
        lines = contents.split("\n")
        num_sites = int(lines[0])
        coords = []
        sp = []
        coord_patt = re.compile(
            r"(\w+)\s+([0-9\-\+\.eEdD]+)\s+([0-9\-\+\.eEdD]+)\s+([0-9\-\+\.eEdD]+)"
        )
        for i in range(2, 2 + num_sites):
            m = coord_patt.search(lines[i])
            if m:
                sp.append(m.group(1))  # this is 1-indexed
                # this is 0-indexed
                # in case of 0.0D+00 or 0.00d+01 old double precision writing
                # replace d or D by e for ten power exponent
                xyz = [val.lower().replace("d", "e") for val in m.groups()[1:4]]
                coords.append([float(val) for val in xyz])
        return Molecule(sp, coords)

    @staticmethod
    def from_string(contents):
        """
        Creates XYZ object from a string.

        Args:
            contents: String representing an XYZ file.

        Returns:
            XYZ object
        """
        if contents[-1] != "\n":
            contents += "\n"
        white_space = r"[ \t\r\f\v]"
        natoms_line = white_space + r"*\d+" + white_space + r"*\n"
        comment_line = r"[^\n]*\n"
        coord_lines = r"(\s*\w+\s+[0-9\-\+\.eEdD]+\s+[0-9\-\+\.eEdD]+\s+[0-9\-\+\.eEdD]+.*\n)+"
        frame_pattern_text = natoms_line + comment_line + coord_lines
        pat = re.compile(frame_pattern_text, re.MULTILINE)
        mols = []
        for xyz_match in pat.finditer(contents):
            xyz_text = xyz_match.group(0)
            mols.append(XYZ._from_frame_string(xyz_text))
        return XYZ(mols)

    @staticmethod
    def from_file(filename):
        """
        Creates XYZ object from a file.

        Args:
            filename: XYZ filename

        Returns:
            XYZ object
        """
        with zopen(filename) as f:
            return XYZ.from_string(f.read())

    def _frame_str(self, frame_mol):
        output = [str(len(frame_mol)), frame_mol.composition.formula]
        fmtstr = "{{}} {{:.{0}f}} {{:.{0}f}} {{:.{0}f}}".format(self.precision)
        for site in frame_mol:
            output.append(fmtstr.format(site.specie, site.x, site.y, site.z))
        return "\n".join(output)

    def __str__(self):
        return "\n".join([self._frame_str(mol) for mol in self._mols])

    def write_file(self, filename):
        """
        Writes XYZ to file.

        Args:
            filename: File name of output file.
        """
        with zopen(filename, "wt") as f:
            f.write(self.__str__())
<|endoftext|>