Skip to content

Commit 079e8e6

Browse files
author
Worvast
authored
Merge pull request #43 from DevoInc/release-next
2.0.3 improvements in devo.commons logging and configuration objects
2 parents 8ab7a8c + fc292a6 commit 079e8e6

File tree

8 files changed

+221
-32
lines changed

8 files changed

+221
-32
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [2.0.3] - 2019-01-23
8+
#### Changed
9+
* Devo.common get_log() has more flags for better customization
10+
11+
#### Added
12+
* Sender for_logging() creation now verify where is tag flag
13+
* Functions for configuration (save, leng, etc)
14+
715
## [2.0.2] - 2019-01-23
816
#### Fixed
917
* devo.common logging handler

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
[![master Build Status](https://travis-ci.com/DevoInc/python-sdk.svg?branch=master)](https://travis-ci.com/DevoInc/python-sdk) [![LICENSE](https://img.shields.io/dub/l/vibe-d.svg)](https://github.com/DevoInc/python-sdk/blob/master/LICENSE)
33

4-
[![wheel](https://img.shields.io/badge/wheel-yes-brightgreen.svg)](https://pypi.org/project/devo-sdk/) [![version](https://img.shields.io/badge/version-2.0.2-blue.svg)](https://pypi.org/project/devo-sdk/) [![python](https://img.shields.io/badge/python-2.7%20%7C%203.3%20%7C%203.4%20%7C%203.5%20%7C%203.6%20%7C%203.7-blue.svg)](https://pypi.org/project/devo-sdk/)
4+
[![wheel](https://img.shields.io/badge/wheel-yes-brightgreen.svg)](https://pypi.org/project/devo-sdk/) [![version](https://img.shields.io/badge/version-2.0.3-blue.svg)](https://pypi.org/project/devo-sdk/) [![python](https://img.shields.io/badge/python-2.7%20%7C%203.3%20%7C%203.4%20%7C%203.5%20%7C%203.6%20%7C%203.7-blue.svg)](https://pypi.org/project/devo-sdk/)
55

66

77
# Devo Python SDK

devo/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__description__ = 'Devo Python Library.'
22
__url__ = 'http://www.devo.com'
3-
__version__ = "2.0.2"
3+
__version__ = "2.0.3"
44
__author__ = 'Devo'
55
__author_email__ = 'support@devo.com'
66
__license__ = 'MIT'

devo/common/generic/configuration.py

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ class Configuration:
1313
"""
1414
Main class for load config files, and extract config objects
1515
"""
16-
def __init__(self):
16+
def __init__(self, path=None, section=None):
1717
self.cfg = dict()
18+
if path is not None:
19+
self.load_config(path=path, section=section)
1820

1921
def __load_cfg(self, cfg, section=None):
2022
"""Load Configuration
@@ -27,7 +29,7 @@ def __load_cfg(self, cfg, section=None):
2729
self.mix(cfg[section])
2830
else:
2931
self.mix(cfg)
30-
return self
32+
return None
3133

3234
def load_json(self, path, section=None):
3335
"""Load Json Configuration
@@ -73,6 +75,39 @@ def load_config(self, path, section=None):
7375

7476
raise ConfigurationException("Configuration file type unknown or not supportted: %s" %path)
7577

78+
def save(self, path=None, save_bak=False):
79+
if path is None:
80+
return False
81+
82+
if os.path.isfile(path):
83+
os.rename(path, "{}.bak".format(path))
84+
try:
85+
with open(path, 'w') as file:
86+
if path.endswith('.json'):
87+
json.dump(self.cfg, file)
88+
if path.endswith('.yaml') or path.endswith('.yml'):
89+
try:
90+
import yaml
91+
except ImportError as import_error:
92+
print(str(import_error),
93+
"- Use 'pip install pyyaml' or install this "
94+
"package with [click] option")
95+
yaml.dump(self.cfg, file, default_flow_style=False)
96+
if os.path.isfile("{}.bak".format(path)) and not save_bak:
97+
self.delete_file("{}.bak".format(path))
98+
return True
99+
except Exception:
100+
if os.path.isfile(path):
101+
self.delete_file(path)
102+
if os.path.isfile("{}.bak".format(path)):
103+
os.rename("{}.bak".format(path), path)
104+
return False
105+
106+
@staticmethod
107+
def delete_file(file):
108+
if os.path.isfile(file):
109+
os.remove(file)
110+
76111
@staticmethod
77112
def __search_default_config_file():
78113
return "json" if os.path.exists(os.path.expanduser("~/.devo.json")) \
@@ -132,11 +167,28 @@ def secure_mix(self, cfg):
132167
if key not in self.cfg.keys():
133168
self.cfg[key] = cfg[key]
134169

135-
def get(self):
170+
def get(self, *args, **kwargs):
136171
"""Get the configuration as dict
137172
138173
:return: Return the configuration dict
139174
"""
175+
key = kwargs.get("key", None)
176+
aux_dict = kwargs.get("aux_dict", None)
177+
178+
if args:
179+
if isinstance(args[0], list):
180+
key = args[0]
181+
else:
182+
key = list(args)
183+
if key:
184+
if aux_dict is None:
185+
aux_dict = self.cfg
186+
if isinstance(key, list):
187+
if len(key) > 1:
188+
return self.get(key=key[1:], aux_dict=aux_dict[key[0]])
189+
return aux_dict[key[0]]
190+
return self.cfg[key]
191+
140192
return self.cfg
141193

142194
def keys(self, prop):
@@ -148,15 +200,12 @@ def keys(self, prop):
148200
return False
149201
return True
150202

151-
#DEPRECATE THIS FOR 2.0
152203
def key_exist(self, prop):
153204
"""Check if exist property and if not then set to None
154205
155206
:param prop: Property to check
156207
"""
157-
if prop not in self.cfg:
158-
return False
159-
return True
208+
return self.keys(prop)
160209

161210
def set(self, key_list, value):
162211
""" Set value of dict
@@ -184,3 +233,13 @@ def set_key_chain(aux_dict, key_list, value):
184233
key_list[1:],
185234
value)
186235
return aux_dict
236+
237+
def __getitem__(self, key):
238+
return self.cfg[key]
239+
240+
def __setitem__(self, key, value):
241+
self.cfg[key] = value
242+
return None
243+
244+
def __str__(self):
245+
return str(self.cfg)

devo/common/logging/log.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,23 @@
77

88
def get_log(path_base="./",
99
file_name="history.log",
10-
msg_format="'%(asctime)s %(levelname)s %(message)s'"):
10+
msg_format="'%(asctime)s %(levelname)s %(message)s'",
11+
name="log",
12+
max_size=2097152,
13+
backup_count=5,
14+
level=logging.DEBUG):
1115
"""Initialize logger for self process log
1216
1317
:return: Log object
1418
"""
15-
logger = logging.getLogger('log')
16-
logger.addHandler(set_handler(os.path.join(path_base, file_name), msg_format))
17-
logger.setLevel(logging.DEBUG)
19+
20+
full_path = os.path.join(path_base, file_name)
21+
if not os.path.exists(os.path.dirname(full_path)):
22+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
23+
24+
logger = logging.getLogger(name)
25+
logger.addHandler(set_handler(full_path, msg_format, max_size, backup_count))
26+
logger.setLevel(level)
1827
return logger
1928

2029

@@ -26,11 +35,12 @@ def set_formatter(msg_format):
2635
return logging.Formatter(msg_format)
2736

2837

29-
def set_handler(path, msg_format):
38+
def set_handler(path, msg_format, max_size, backup_count):
3039
"""Initialize handler for logger
3140
3241
:return: RotatingFileHandler object
3342
"""
34-
handler = RotatingFileHandler(path, maxBytes=2097152, backupCount=5)
43+
handler = RotatingFileHandler(path, maxBytes=max_size,
44+
backupCount=backup_count)
3545
handler.setFormatter(set_formatter(msg_format))
3646
return handler

devo/sender/data.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,17 +436,25 @@ def set_logger_tag(self, tag):
436436
self._logger_tag = tag
437437

438438
@staticmethod
439-
def for_logging(config, con_type="SSL", tag="test.drop.free"):
439+
def for_logging(config, con_type="SSL", tag=None, level=10):
440440
""" Function for create Sender object from config file to use in
441441
logging handler
442442
:param config: config Devo file
443443
:param con_type: type of connection
444444
:param tag: tag for the table
445+
:param level: level of logger
446+
:param formatter: log formatter
445447
:return: Sender object
446448
"""
447449
con = Sender.from_config(config, con_type)
448-
con.set_logger_tag(tag)
449-
con.set_level = 7
450+
if tag:
451+
con.set_logger_tag(tag)
452+
elif "tag" in config.keys():
453+
con.set_logger_tag(config['tag'])
454+
else:
455+
con.set_logger_tag("test.keep.free")
456+
457+
con.set_level = level
450458
return con
451459

452460
@staticmethod

docs/common.md

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ This library add utilities for other packages.
77
- Unification in the way of treating date formats
88
- Unification in the way of treating configuration files
99
- Logging functions
10-
- Custom memoize def
1110

1211
#### Date Formats
1312
- Fixed format: As described on [Official Python Docs](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior). Accepted formats are:
@@ -28,13 +27,84 @@ This library add utilities for other packages.
2827
- month(): Return 30 * 24 * 60 * 60
2928

3029

30+
#### Standard Devo logging file
31+
32+
Devo commons gives you a function, with enough parameters for your personalization, to get a rotatting log handler:
33+
34+
```python
35+
def get_log(path_base="./",
36+
file_name="history.log",
37+
msg_format="'%(asctime)s %(levelname)s %(message)s'",
38+
name="log",
39+
max_size=2097152,
40+
backup_count=5,
41+
level=logging.DEBUG):
42+
```
43+
44+
45+
You can use this handler with sender object, you can see more info in ['Sender readme'](sender.md######Third example)
46+
3147
#### Standard Devo configuration file
3248

3349
Devo Common contains the [`Configuration`](common/generic/configuration.py)
34-
class to read JSON configuration files
50+
class to read JSON and YAML configuration files
3551
and automix an array with the file.
3652

3753
You can see in several Devo libraries that the CLI allows the reading of a
3854
config.json file, they all use this class to load them, and in each of the
3955
libraries you can find the format they use, in addition to examples of use in
4056
this class tests.
57+
58+
You can read json or yaml file and save to obj faster:
59+
60+
```python
61+
from devo.common import Configuration
62+
63+
config = Configuration("/path/o/my/file.yaml")
64+
```
65+
66+
You can use all these options for access, modify or use this object:
67+
68+
```python
69+
from devo.common import Configuration
70+
71+
#Create
72+
config = Configuration("/path/o/my/file.yaml")
73+
74+
75+
# Get key
76+
value = config['keyOne']
77+
# or
78+
value = config.get("keyOne")
79+
# ---
80+
81+
# Get key chain
82+
value = config['keyOne']['subKey']['id']
83+
# or
84+
value = config.get("keyOne", "subKey", "id")
85+
# or
86+
value = config.get(["keyOne", "subKey", "id"])
87+
# ---
88+
89+
90+
# Set key
91+
config['keyTwo'] = "value"
92+
# or
93+
config.set('keyTwo', "value")
94+
# ---
95+
96+
# Set key chain
97+
config['keyTwo'] = {}
98+
config['keyTwo']['subKey'] = {}
99+
config['keyTwo']['subKey']['id'] = "value"
100+
101+
# or
102+
config['keyTwo'] = {'subkey': {'id': "value"}}
103+
104+
# or
105+
config.set(["keyTwo", "subKey", "id"], "value")
106+
107+
108+
# Save to file
109+
config.save("file/path.ext")
110+
```

0 commit comments

Comments
 (0)