1
|
|
|
# |
2
|
|
|
# Copyright (C) 2018 Satoru SATOH <ssato @ redhat.com> |
3
|
|
|
# License: MIT |
4
|
|
|
# |
5
|
|
|
# pylint: disable=invalid-name |
6
|
|
|
r"""Functions for value objects represent inputs and outputs. |
7
|
|
|
|
8
|
|
|
.. versionadded:: 0.9.5 |
9
|
|
|
|
10
|
|
|
- Add functions to make and process input and output object holding some |
11
|
|
|
attributes like input and output type (path, stream or pathlib.Path object), |
12
|
|
|
path, opener, etc. |
13
|
|
|
""" |
14
|
|
|
from __future__ import absolute_import |
15
|
|
|
|
16
|
|
|
import anyconfig.processors |
17
|
|
|
import anyconfig.utils |
18
|
|
|
|
19
|
|
|
from anyconfig.globals import ( |
20
|
|
|
IOInfo, IOI_NONE, IOI_PATH_STR, IOI_PATH_OBJ, IOI_STREAM, |
21
|
|
|
UnknownFileTypeError |
22
|
|
|
) |
23
|
|
|
|
24
|
|
|
|
25
|
|
|
def guess_io_type(obj): |
26
|
|
|
"""Guess input or output type of ``obj``. |
27
|
|
|
|
28
|
|
|
:param obj: a path string, a pathlib.Path or a file / file-like object |
29
|
|
|
:return: IOInfo type defined in anyconfig.globals.IOI_TYPES |
30
|
|
|
|
31
|
|
|
>>> apath = "/path/to/a_conf.ext" |
32
|
|
|
>>> assert guess_io_type(apath) == IOI_PATH_STR |
33
|
|
|
|
34
|
|
|
>>> from anyconfig.compat import pathlib |
35
|
|
|
>>> if pathlib is not None: |
36
|
|
|
... assert guess_io_type(pathlib.Path(apath)) == IOI_PATH_OBJ |
37
|
|
|
>>> assert guess_io_type(open(__file__)) == IOI_STREAM |
38
|
|
|
""" |
39
|
|
|
if obj is None: |
40
|
|
|
return IOI_NONE |
41
|
|
|
elif anyconfig.utils.is_path(obj): |
42
|
|
|
return IOI_PATH_STR |
43
|
|
|
elif anyconfig.utils.is_path_obj(obj): |
44
|
|
|
return IOI_PATH_OBJ |
45
|
|
|
|
46
|
|
|
return IOI_STREAM |
47
|
|
|
|
48
|
|
|
|
49
|
|
|
def inspect_io_obj(obj): |
50
|
|
|
""" |
51
|
|
|
:param obj: a path string, a pathlib.Path or a file / file-like object |
52
|
|
|
|
53
|
|
|
:return: A tuple of (objtype, objpath, objopener) |
54
|
|
|
:raises: UnknownFileTypeError |
55
|
|
|
""" |
56
|
|
|
itype = guess_io_type(obj) |
57
|
|
|
|
58
|
|
|
if itype == IOI_PATH_STR: |
59
|
|
|
ipath = anyconfig.utils.normpath(obj) |
60
|
|
|
opener = open |
61
|
|
|
elif itype == IOI_PATH_OBJ: |
62
|
|
|
ipath = anyconfig.utils.normpath(obj.as_posix()) |
63
|
|
|
opener = obj.open |
64
|
|
|
elif itype == IOI_STREAM: |
65
|
|
|
ipath = anyconfig.utils.get_path_from_stream(obj) |
66
|
|
|
opener = anyconfig.utils.noop |
67
|
|
|
elif itype == IOI_NONE: |
68
|
|
|
ipath = None |
69
|
|
|
opener = anyconfig.utils.noop |
70
|
|
|
else: |
71
|
|
|
raise UnknownFileTypeError("%r" % obj) |
72
|
|
|
|
73
|
|
|
return (itype, ipath, opener) |
74
|
|
|
|
75
|
|
|
|
76
|
|
|
def make(obj, prs, forced_type=None): |
77
|
|
|
""" |
78
|
|
|
:param obj: a path string, a pathlib.Path or a file / file-like object |
79
|
|
|
:param prs: A list of processor classes |
80
|
|
|
:param forced_type: Forced processor type or processor object |
81
|
|
|
|
82
|
|
|
:return: |
83
|
|
|
Namedtuple object represents a kind of input object such as a file / |
84
|
|
|
file-like object, path string or pathlib.Path object |
85
|
|
|
|
86
|
|
|
:raises: ValueError, UnknownProcessorTypeError, UnknownFileTypeError |
87
|
|
|
""" |
88
|
|
|
if anyconfig.utils.is_ioinfo(obj): |
89
|
|
|
return obj |
90
|
|
|
|
91
|
|
|
if (obj is None or not obj) and forced_type is None: |
92
|
|
|
raise ValueError("obj or forced_type must be some value") |
93
|
|
|
|
94
|
|
|
(itype, ipath, opener) = inspect_io_obj(obj) |
95
|
|
|
psr = anyconfig.processors.find(ipath, prs, forced_type) |
96
|
|
|
|
97
|
|
|
return IOInfo(src=obj, type=itype, path=ipath, processor=psr, |
98
|
|
|
opener=opener) |
99
|
|
|
|
100
|
|
|
# vim:sw=4:ts=4:et: |
101
|
|
|
|