python-fuelclient/fuelclient/cli/serializers.py

153 lines
4.8 KiB
Python

# Copyright 2014 Mirantis, Inc.
#
# 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.
from __future__ import print_function
import json
import os
import six
import yaml
from fuelclient.cli import error
from fuelclient import consts
from fuelclient import utils
class Serializer(object):
"""Serializer class - contains all logic responsible for
printing to stdout, reading and writing files to file system.
"""
serializers = {
"json": {
"w": lambda d: json.dumps(d, indent=4),
"r": utils.safe_deserialize(json.loads)
},
"yaml": {
"w": lambda d: yaml.safe_dump(d, default_flow_style=False),
"r": utils.safe_deserialize(yaml.load)
}
}
format_flags = False
default_format = "yaml"
format = default_format
def __init__(self, format=None):
if format and format in self.serializers:
self.format = format
self.format_flags = True
@property
def serializer(self):
"""Returns dicts with methods for loadin/dumping current fromat.
Returned dict's keys:
* 'w' - from 'writing', method for serializing/dumping data
* 'r' - from 'reading', method for deserializing/loading data
"""
return self.serializers[self.format]
def serialize(self, data):
"""Shortcut for serializing data with current format."""
return self.serializer['w'](data)
def deserialize(self, data):
"""Shortcut for deserializing data with current format."""
return self.serializer['r'](data)
@classmethod
def from_params(cls, params):
return cls(format=getattr(params,
consts.SERIALIZATION_FORMAT_FLAG, None))
def print_formatted(self, data):
print(self.serializer["w"](data))
def print_to_output(self, formatted_data, arg, print_method=print):
if self.format_flags:
self.print_formatted(formatted_data)
else:
if six.PY2 and isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
print_method(arg)
def prepare_path(self, path):
return "{0}.{1}".format(
path, self.format
)
def write_to_path(self, path, data):
full_path = self.prepare_path(path)
return self.write_to_full_path(full_path, data)
def write_to_full_path(self, path, data):
try:
with open(path, "w") as file_to_write:
self.write_to_file(file_to_write, data)
except IOError as e:
raise error.InvalidFileException(
"Can't write to file '{0}': {1}.".format(
path, e.strerror))
return path
def read_from_file(self, path):
return self.read_from_full_path(self.prepare_path(path))
def read_from_full_path(self, full_path):
try:
with open(full_path, "r") as file_to_read:
return self.serializer["r"](file_to_read.read())
except IOError as e:
raise error.InvalidFileException(
"Can't open file '{0}': {1}.".format(full_path, e.strerror))
def write_to_file(self, file_obj, data):
"""Writes to opened file or file like object
:param file_obj: opened file
:param data: any serializable object
"""
serialized = self.serializer["w"](data)
file_obj.write(serialized)
class FileFormatBasedSerializer(Serializer):
def get_serializer(self, path):
extension = os.path.splitext(path)[1][1:]
if extension not in self.serializers:
raise error.BadDataException(
'No serializer for provided file {0}'.format(path))
return self.serializers[extension]
def write_to_file(self, full_path, data):
serializer = self.get_serializer(full_path)
with open(full_path, "w+") as f:
f.write(serializer["w"](data))
return full_path
def read_from_file(self, full_path):
serializer = self.get_serializer(full_path)
with open(full_path, "r") as f:
return serializer["r"](f.read())
def listdir_without_extensions(dir_path):
return six.moves.filter(
lambda f: f != "",
six.moves.map(
lambda f: f.split(".")[0],
os.listdir(dir_path)
)
)