feilian 1.1.2__py3-none-any.whl → 1.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of feilian might be problematic. Click here for more details.

feilian/__init__.py CHANGED
@@ -6,7 +6,7 @@ from .dataframe import is_empty_text, is_nonempty_text, is_blank_text, is_non_bl
6
6
  from .datetime import format_time, format_date
7
7
  from .arg import ArgValueParser
8
8
  from .json import read_json, save_json
9
- from .about import __version__
9
+ from .version import __version__
10
10
 
11
11
  __all__ = [
12
12
  'ensure_parent_dir_exist',
feilian/arg.py CHANGED
@@ -1,6 +1,30 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- from typing import Union, List, Any, Iterable, Callable, Set, Optional, Tuple
3
+ from typing import Union, List, Any, Iterable, Callable, Set, Optional, Tuple, Dict, Hashable
4
+ try:
5
+ from typing import Literal
6
+ except ImportError:
7
+ from typing_extensions import Literal
8
+
9
+ _build_in_na_checkers = {
10
+ 'always_na': lambda x: True,
11
+ 'never_na': lambda x: False,
12
+ 'is_none': lambda x: x is None,
13
+ }
14
+ _NA_CHECKER_TYPES = Union[Callable[[Any], bool], Literal['always_na', 'never_na', 'is_none']]
15
+
16
+ _build_in_na_converters = {
17
+ 'none': lambda x: None,
18
+ 'self': lambda x: x,
19
+ 'empty': lambda x: [],
20
+ 'single': lambda x: [x],
21
+ }
22
+ _NA_CONVERTER_TYPES = Union[Callable[[Any], Any], Literal['none', 'self', 'empty', 'single']]
23
+
24
+ def _get_or_default(value: Any, mapping: Dict[Hashable, Any], default_key: Any) -> Any:
25
+ if value is None:
26
+ return mapping[default_key]
27
+ return mapping.get(value, value)
4
28
 
5
29
  class ArgValueParser(object):
6
30
  @classmethod
@@ -92,49 +116,63 @@ class ArgValueParser(object):
92
116
  elem_type=elem_type, allowed_type=allowed_type)
93
117
 
94
118
  @staticmethod
95
- def ensure_list(value: Any, allow_none=True) -> Optional[List[Any]]:
119
+ def ensure_collection(value: Any, expected_type: type, collection_type: Union[type, Tuple[type, ...]],
120
+ na_checker: _NA_CHECKER_TYPES = None, na_converter: _NA_CONVERTER_TYPES = None) -> Any:
121
+ """
122
+ Ensure the value to be a list, tuple or set.
123
+ :param value: any type value
124
+ :param expected_type: expected return type, can be list, tuple or set
125
+ :param collection_type: other collection type to be convert
126
+ :param na_checker: check if `value` is na, default is 'is_none'
127
+ str value means some built-in functions:
128
+ always_na: always treat the value as na
129
+ never_na: never treat the value as na
130
+ is_none: test if the value is `None`
131
+ :param na_converter: if `value` is na, return output of this function, default is 'self'
132
+ str value means some built-in functions:
133
+ none: `None`
134
+ self: the value no changed
135
+ empty: an empty list
136
+ single: a single value list: `[value]`
137
+ :return: expected to be an instance of `expected_type`, or be `None` for some condition
138
+ """
139
+ na_checker = _get_or_default(na_checker, _build_in_na_checkers, 'is_none')
140
+ if na_checker(value):
141
+ na_converter = _get_or_default(na_converter, _build_in_na_converters, 'self')
142
+ return na_converter(value)
143
+ if isinstance(value, expected_type):
144
+ return value
145
+ if isinstance(value, collection_type):
146
+ return expected_type(value)
147
+ return expected_type([value])
148
+
149
+ @classmethod
150
+ def ensure_list(cls, value: Any, na_checker: _NA_CHECKER_TYPES = None,
151
+ na_converter: _NA_CONVERTER_TYPES = None) -> Optional[List[Any]]:
96
152
  """
97
153
  Ensure the value to be a list.
98
- If value is `None`, return `None` if `allow_none` is `True`, else return `[None]`.
154
+ See more arg docs in `ensure_collection()`.
99
155
  """
100
- if value is None and allow_none:
101
- if allow_none:
102
- return value
103
- return [value]
104
- if isinstance(value, list):
105
- return value
106
- if isinstance(value, (set, tuple)):
107
- return list(value)
108
- return [value]
156
+ return cls.ensure_collection(value, expected_type=list, collection_type=(tuple, set),
157
+ na_checker=na_checker, na_converter=na_converter)
109
158
 
110
- @staticmethod
111
- def ensure_tuple(value: Any, allow_none=True) -> Optional[Tuple[Any]]:
159
+ @classmethod
160
+ def ensure_tuple(cls, value: Any, na_checker: _NA_CHECKER_TYPES = None,
161
+ na_converter: _NA_CONVERTER_TYPES = None) -> Optional[Tuple[Any]]:
112
162
  """
113
163
  Ensure the value to be a tuple.
114
- If value is `None`, return `None` if `allow_none` is `True`, else return `(None, )`.
164
+ See more arg docs in `ensure_collection()`.
115
165
  """
116
- if value is None and allow_none:
117
- if allow_none:
118
- return value
119
- return (value,)
120
- if isinstance(value, tuple):
121
- return value
122
- if isinstance(value, (set, list)):
123
- return tuple(value)
124
- return (value,)
166
+ return cls.ensure_collection(value, expected_type=tuple, collection_type=(list, set),
167
+ na_checker=na_checker, na_converter=na_converter)
125
168
 
126
- @staticmethod
127
- def ensure_set(value: Any, allow_none=True) -> Optional[Set[Any]]:
169
+ @classmethod
170
+ def ensure_set(cls, value: Any, na_checker: _NA_CHECKER_TYPES = None,
171
+ na_converter: _NA_CONVERTER_TYPES = None) -> Optional[Set[Any]]:
128
172
  """
129
173
  Ensure the value to be a set.
130
- If value is `None`, return `None` if `allow_none` is `True`, else return `{None}`.
174
+ See more arg docs in `ensure_collection()`.
131
175
  """
132
- if value is None and allow_none:
133
- if allow_none:
134
- return value
135
- return {value}
136
- if isinstance(value, set):
137
- return value
138
- if isinstance(value, (tuple, list)):
139
- return set(value)
140
- return {value}
176
+ return cls.ensure_collection(value, expected_type=set, collection_type=(list, tuple),
177
+ na_checker=na_checker, na_converter=na_converter)
178
+
feilian/dataframe.py CHANGED
@@ -4,7 +4,12 @@
4
4
  Encapsulate methods for pandas `DataFrame`.
5
5
  """
6
6
 
7
- from typing import Union, Iterable, Dict, Literal, List, Any, Sequence, Callable, Tuple, Hashable
7
+ from typing import Union, Iterable, Dict, List, Any, Sequence, Callable, Tuple, Hashable
8
+ try:
9
+ from typing import Literal
10
+ except ImportError:
11
+ from typing_extensions import Literal
12
+
8
13
  import os
9
14
  import pandas as pd
10
15
  import random
@@ -19,14 +24,16 @@ if pd_version[0] < 1 or (pd_version[0] == 1 and pd_version[1] < 5):
19
24
 
20
25
  def read_dataframe(file: str, *args, sheet_name=0,
21
26
  file_format: Literal['csv', 'tsv', 'json', 'xlsx'] = None,
22
- jsonl=False, **kwargs) -> Union[pd.DataFrame, Dict[str, pd.DataFrame]]:
27
+ jsonl=False, dtype: pd._typing.DtypeArg = None,
28
+ **kwargs) -> Union[pd.DataFrame, Dict[str, pd.DataFrame]]:
23
29
  """
24
30
  read file as pandas `DataFrame`
25
31
  :param file: the file to be read
26
32
  :param args: extra args for `pd.read_xx()`
27
33
  :param sheet_name: `sheet_name` for `pd.read_excel()`
28
34
  :param file_format: csv, tsv, json ,xlsx
29
- :param jsonl: jsonl format or not, only used in json format
35
+ :param jsonl: jsonl format or not, only used in json format
36
+ :param dtype: `dtype` for `pd.read_xx()`
30
37
  :param kwargs: extra kwargs for `pd.read_xx()`
31
38
  """
32
39
  # decide the file format
@@ -47,17 +54,17 @@ def read_dataframe(file: str, *args, sheet_name=0,
47
54
  kwargs['delimiter'] = '\t'
48
55
 
49
56
  if file_format == 'csv':
50
- return pd.read_csv(file, *args, **kwargs)
57
+ return pd.read_csv(file, *args, dtype=dtype, **kwargs)
51
58
  elif file_format == 'xlsx':
52
- return pd.read_excel(file, *args, sheet_name=sheet_name, **kwargs)
59
+ return pd.read_excel(file, *args, sheet_name=sheet_name, dtype=dtype, **kwargs)
53
60
  elif file_format == 'json':
54
- return pd.read_json(file, *args, lines=jsonl, **kwargs)
61
+ return pd.read_json(file, *args, lines=jsonl, dtype=dtype, **kwargs)
55
62
  else:
56
63
  raise IOError(f"Unknown file format: {file}")
57
64
 
58
65
  def save_dataframe(file: Union[str, 'pd.WriteBuffer[bytes]', 'pd.WriteBuffer[str]'],
59
66
  df: Union[pd.DataFrame, Iterable[Union[pd.Series, Dict[str, Any]]]],
60
- *args,
67
+ *args, sheet_name='Sheet1',
61
68
  file_format: Literal['csv', 'tsv', 'json', 'xlsx'] = None,
62
69
  index=False, index_label=None,
63
70
  encoding='utf-8', newline='\n',
@@ -72,8 +79,10 @@ def save_dataframe(file: Union[str, 'pd.WriteBuffer[bytes]', 'pd.WriteBuffer[st
72
79
  :param file: where to save the data to
73
80
  :param df: the data
74
81
  :param args: extra args for df.to_xx()
82
+ :param sheet_name: `sheet_name` for excel format
75
83
  :param file_format: csv, tsv, json, xlsx
76
- :param index: save index or not, see docs in df.to_csv()
84
+ :param index: save index or not, see docs in df.to_csv();
85
+ if set as str and `index_label` not set, `index_label` will be set as this
77
86
  :param index_label: header for the index when `index` is `True`
78
87
  :param encoding: text file encoding
79
88
  :param newline: text file newline
@@ -114,6 +123,10 @@ def save_dataframe(file: Union[str, 'pd.WriteBuffer[bytes]', 'pd.WriteBuffer[st
114
123
  if isinstance(file, (str, os.PathLike)):
115
124
  ensure_parent_dir_exist(file)
116
125
 
126
+ # compatible for set index just use arg `index`
127
+ if index_label is None and isinstance(index, str):
128
+ index, index_label = True, index
129
+
117
130
  # tsv is actually a csv
118
131
  if file_format == 'tsv':
119
132
  file_format = 'csv'
@@ -124,7 +137,7 @@ def save_dataframe(file: Union[str, 'pd.WriteBuffer[bytes]', 'pd.WriteBuffer[st
124
137
  kwargs[PD_PARAM_NEWLINE] = newline
125
138
  df.to_csv(file, *args, index=index, index_label=index_label, encoding=encoding, **kwargs)
126
139
  elif file_format == 'xlsx':
127
- df.to_excel(file, *args, index=index, index_label=index_label, **kwargs)
140
+ df.to_excel(file, *args, index=index, index_label=index_label, sheet_name=sheet_name, **kwargs)
128
141
  elif file_format == 'json':
129
142
  if jsonl:
130
143
  orient = 'records'
feilian/datetime.py CHANGED
@@ -16,5 +16,6 @@ def format_time(time: Union[str, int, float, datetime.datetime] = None, fmt='%Y-
16
16
  raise ValueError(f"Unexpected type: {type(time)}")
17
17
  return time.strftime(fmt)
18
18
 
19
- def format_date(date: Union[str, int, float, datetime.datetime] = None, sep='-') -> str:
19
+ # when format a date, no sep is used more
20
+ def format_date(date: Union[str, int, float, datetime.datetime] = None, sep='') -> str:
20
21
  return format_time(date, fmt=sep.join(['%Y', '%m', '%d']))
feilian/json.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from typing import Dict, List, Union, Any
4
4
  import json
5
+ from .io import ensure_parent_dir_exist
5
6
 
6
7
  def read_json(filepath: str, encoding='utf-8', **kwargs):
7
8
  """
@@ -15,5 +16,6 @@ def save_json(filepath: str, data: Union[Dict[str, Any], List[Any]],
15
16
  """
16
17
  An agent for `json.dump()` with some default value.
17
18
  """
19
+ ensure_parent_dir_exist(filepath)
18
20
  with open(filepath, 'w', encoding=encoding, newline=newline) as f:
19
21
  json.dump(data, f, indent=indent, ensure_ascii=ensure_ascii, **kwargs)
feilian/string.py ADDED
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from typing import Any, Callable
4
+
5
+ def join_values(*values: Any, sep='', func: Callable[[Any], str] = str, do_trim=False, ignore_empty=False):
6
+ def f():
7
+ for x in values:
8
+ s = func(x)
9
+ if do_trim:
10
+ s = s.strip()
11
+ if s or not ignore_empty:
12
+ yield s
13
+ return sep.join(f())
feilian/version.py ADDED
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from importlib.metadata import version, PackageNotFoundError
4
+
5
+ try:
6
+ __version__ = version("feilian")
7
+ except PackageNotFoundError:
8
+ # package is not installed
9
+ __version__ = "UNKNOWN"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: feilian
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: General data processing tool.
5
5
  Home-page: https://github.com/darkpeath/feilian
6
6
  Author: darkpeath
@@ -0,0 +1,12 @@
1
+ feilian/__init__.py,sha256=D_OYSAfDALQnRsbaAXMnHyC0LtykaIXLTHq7XNcsYjU,763
2
+ feilian/arg.py,sha256=lGZ99RkU9uhE_ziaFK2SClS3vrygteNNxTm3i_68SWw,8359
3
+ feilian/dataframe.py,sha256=121EcLvAkbBWv_antTABTJUaq3MIl1IHh1bPjaPCC0c,9853
4
+ feilian/datetime.py,sha256=IONvWhLeGEy9IVe6GWKEW3FhrfRrShyhGP8-RTf9r3c,763
5
+ feilian/io.py,sha256=aYN3QwWcLoRKzhGMNutqdkmxArVcXfeWXzxCB07LcFc,155
6
+ feilian/json.py,sha256=1GsnL-CASi4xBaycMN-Tw1ytxty7GeL2wmt7nfLfnB4,754
7
+ feilian/string.py,sha256=G_X3dnR0Oxmi4hXF-6E5jm5M7GPjGoMYrSMyI1dj6Z4,370
8
+ feilian/version.py,sha256=qI88ygIU5YG1b7BXxWD6l2jeVvcb78eQ__3BmRl3KCU,217
9
+ feilian-1.1.4.dist-info/METADATA,sha256=pc2HUo4iTEzUOakzR-Js_SiNrdqHyUSg68h_HRw0dh4,911
10
+ feilian-1.1.4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
11
+ feilian-1.1.4.dist-info/top_level.txt,sha256=1Q2-B6KJrcTr7drW_kik35PTVEUJLPP4wVrn0kYKwGw,8
12
+ feilian-1.1.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.1)
2
+ Generator: bdist_wheel (0.41.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
feilian/about.py DELETED
@@ -1,5 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- VERSION = (1, 1, 2)
4
-
5
- __version__ = ".".join(map(str, VERSION))
@@ -1,11 +0,0 @@
1
- feilian/__init__.py,sha256=oDG4bUXVJpqC2Q1Yhwt2AY-8-NFX1ZKcv5YyXYKuCC4,761
2
- feilian/about.py,sha256=_-XUlhoKoRnnHfLXI02xXzYtCUI83o2ww0MU8hlm0Mg,88
3
- feilian/arg.py,sha256=NwaBcKpHv7m00D5_LFuR8clQBSGX5brVXnh7ubGssas,5918
4
- feilian/dataframe.py,sha256=ZqGLNQLKFTGaJiK2dw41ch0IIRJhLWTHpdLBHzgafJk,9260
5
- feilian/datetime.py,sha256=FEZOf3pYDkjE1A1mPJU6eXmj6Mi6jyJgQxCK-04WzuI,722
6
- feilian/io.py,sha256=aYN3QwWcLoRKzhGMNutqdkmxArVcXfeWXzxCB07LcFc,155
7
- feilian/json.py,sha256=fcGHxwUEpCVaMkE9HoILC693e1_H-P6J4a8Y_6Locig,676
8
- feilian-1.1.2.dist-info/METADATA,sha256=sXlS7cKZR0vLodpiVzrxPd2UUpbc-DT9L1DlQ-tYyn4,911
9
- feilian-1.1.2.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
10
- feilian-1.1.2.dist-info/top_level.txt,sha256=1Q2-B6KJrcTr7drW_kik35PTVEUJLPP4wVrn0kYKwGw,8
11
- feilian-1.1.2.dist-info/RECORD,,