CsvWrite.py :  » Development » SnapLogic » snaplogic » components » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » SnapLogic 
SnapLogic » snaplogic » components » CsvWrite.py
# $SnapHashLicense:
# 
# SnapLogic - Open source data services
# 
# Copyright (C) 2009, SnapLogic, Inc.  All rights reserved.
# 
# See http://www.snaplogic.org for more information about
# the SnapLogic project. 
# 
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the LEGAL file
# at the top of the source tree.
# 
# "SnapLogic" is a trademark of SnapLogic, Inc.
# 
# 
# $

#    $Id: CsvWrite.py 10330 2009-12-24 22:13:38Z grisha $

"""
CsvWrite Component.

This component provides a single input view and the data sent to this
view is written out to a csv format file.

"""

import codecs
import os
from decimal import Decimal
from datetime import datetime

from snaplogic.common.data_types import Record
from snaplogic.common.snap_exceptions import *
from snaplogic.common.data_types import SnapNumber,SnapString,SnapDateTime
from snaplogic.common import version_info
from snaplogic.snapi_base import keys
from snaplogic.cc import component_api
from snaplogic.cc.component_api import ComponentAPI
import snaplogic.cc.prop as prop
from snaplogic.components import FileUtils
from snaplogic.common import snap_log

class CsvWrite(ComponentAPI):
    """
    This class implements the CSV write component.
    
    It provides the functionality of writing output in CSV format to a file.
    
    """
    
    api_version = '1.0'
    component_version = '1.2'
    
    capabilities = {
        ComponentAPI.CAPABILITY_INPUT_VIEW_LOWER_LIMIT    : 1,
        ComponentAPI.CAPABILITY_INPUT_VIEW_UPPER_LIMIT    : 1,
        ComponentAPI.CAPABILITY_OUTPUT_VIEW_LOWER_LIMIT   : 0,
        ComponentAPI.CAPABILITY_OUTPUT_VIEW_UPPER_LIMIT   : 0
    }
    
    component_description = "Writes CSV format output to files"
    component_label = "CSV Writer"
    component_doc_uri = "https://www.snaplogic.org/trac/wiki/Documentation/%s/ComponentRef/CsvWrite" % \
                                                        version_info.doc_uri_version
    
    def validate_config_file(self):
        """If a config file is provided, then validate its contents."""
        for k in self.config_dictionary:
            if k == "root_directory":
                if not os.path.exists(self.config_dictionary[k]):
                    raise SnapComponentConfigError("The path specified for root (%s) is not valid" % 
                                                   self.config_dictionary[k])
            elif k == "schemes":
                # Make sure "schemes" contains only the schemes we support
                FileUtils.validate_schemes(self.config_dictionary.get("schemes"), FileUtils.writer_schemes)
            else:
                # No other config file param is supported.
                raise SnapComponentConfigError("Unexpected config file entry (%s) encountered" % k)
            
    def create_resource_template(self):
        """
        Create CsvWrite resource definition template. It consists of
        
        filename  : The name of the file to write into.
        delimiter : The field delimiter that should be used (defaults to ",").
        header    : Set this to True, if a header with all the field names need to be written out in the first line.
        
        """    
        self.set_property_def('filename',
                              prop.SimpleProp("File name", SnapString, "The name of the file that is written to", 
                                              None, True))
        
        self.set_property_def('delimiter', prop.SimpleProp("Delimiter", SnapString, "The field delimiter", None, True))
        self.set_property_value('delimiter', ",")
        
        self.set_property_def('header', prop.SimpleProp("Header Present", "boolean", "Does the file have a header", 
                                                        None, True))
        self.set_property_value('header', False)
        self._add_quote_prop()
    
    def _add_quote_prop(self):
        """
        Adds quote property
        
        """
        self.set_property_def('quote', prop.SimpleProp("Quote character", SnapString, 
                                                       "Character used to quote an entry if a delimiter appears in it", 
                                                       None))
        
    def upgrade_1_0_to_1_1(self):
        """ 
        Add quote property
        
        """
        self._add_quote_prop()
        delim = self.get_property_value('delimiter')
        
    def upgrade_1_1_to_1_2(self):
        """
        No-op upgrade only to change component doc URI during the upgrade
        which will be by cc_info before calling this method.
        
        """
        pass
    
    def suggest_resource_values(self, err_obj):
        """Suggest that "," be used as delimiter, if no delimiter value has been selected."""
        val = self.get_property_value("delimiter")
        if not val:
            self.set_property_value("delimiter", ",")

    def validate(self, err_obj):
        """
        Component-specific validation logic.
        Validate that the URI scheme specified for the filename is one of the allowed
        schemes as specified in the component config file.
        
        @param err_obj: Object for error reporting
        @type err_obj: L{SimplePropErr} or L{ListPropErr} or L{DictPropErr}  
        """
        
        # Validate that the filename complies with the allowed URI schemes,
        # unless it's specified via a parameter 
        FileUtils.validate_filename_property(self.get_property_value("filename"), "filename", err_obj, 
                                   self.config_dictionary.get("schemes"), FileUtils.writer_schemes)

    
    def execute(self, input_views, output_views):
        """Execute the CSV writing functionality of the component."""
        try:
            input_view = input_views.values()[keys.SINGLE_VIEW] 
        except IndexError:
            raise SnapComponentError("No input view connected")

        self._filename = self.get_property_value("filename")
        self._delim    = self.get_property_value("delimiter")
        self._header   = self.get_property_value("header")
        
        self._filename = FileUtils.get_file_location(self._filename, self.config_dictionary)
        # Validate filename URI scheme
        error = FileUtils.validate_file_scheme(self._filename, self.config_dictionary.get("schemes"), FileUtils.writer_schemes)
        if error is not None:
            raise SnapComponentError(error)
        
        if self._filename.startswith('file://'):
            if os.name == 'nt':
                self._filename = self._filename[len('file:///'):]
            else:
                self._filename = self._filename[len('file://'):]

        self._file = codecs.open(self._filename, "w", 'utf-8')
        
        self.log(snap_log.LEVEL_INFO, "Writing: %s" % self._filename)
        
        quote = self.get_property_value('quote')
        if not quote:
            # If quote isn't provided, use double quote
            quote = '"'
        quoted_quote = "%s%s" % (quote, quote)
        
        try:
            first_record = True    
            record = input_view.read_record()
            while record is not None:
                first_field = True
                for field_name in record.field_names:
                    if first_record:
                        first_record = False
                        if self._header:
                            self._file.write(self._delim.join(record.field_names))
                            self._file.write(os.linesep)
                    if first_field:
                        first_field = False
                    else:
                        self._file.write(self._delim)
                    val = record[field_name]
                    if val is not None:
                        if isinstance(val, datetime) or isinstance(val, Decimal):
                            val = str(val)
                        has_quotes = quote in val
                        if self._delim in val or has_quotes or '\r' in val or '\n' in val:
                            if has_quotes:
                                val = val.replace(quote, quoted_quote)
                            val = quote + val + quote
                        self._file.write(val)
                self._file.write(os.linesep)
                record = input_view.read_record()
        finally:
            self._file.close()
                
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.