Code cleanup / reorganize

This commit is contained in:
Alexandre Aubin 2021-08-27 21:17:39 +02:00
parent 5631719836
commit a263039958
5 changed files with 46 additions and 56 deletions

View file

@ -4,7 +4,9 @@ import re
import logging import logging
import argparse import argparse
import copy import copy
import datetime
from collections import deque, OrderedDict from collections import deque, OrderedDict
from json.encoder import JSONEncoder
from moulinette import m18n from moulinette import m18n
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
@ -560,3 +562,40 @@ class PositionalsFirstHelpFormatter(argparse.HelpFormatter):
# prefix with 'usage:' # prefix with 'usage:'
return "%s%s\n\n" % (prefix, usage) return "%s%s\n\n" % (prefix, usage)
class JSONExtendedEncoder(JSONEncoder):
"""Extended JSON encoder
Extend default JSON encoder to recognize more types and classes. It will
never raise an exception if the object can't be encoded and return its repr
instead.
The following objects and types are supported:
- set: converted into list
"""
def default(self, o):
import pytz # Lazy loading, this takes like 3+ sec on a RPi2 ?!
"""Return a serializable object"""
# Convert compatible containers into list
if isinstance(o, set) or (hasattr(o, "__iter__") and hasattr(o, "next")):
return list(o)
# Display the date in its iso format ISO-8601 Internet Profile (RFC 3339)
if isinstance(o, datetime.date):
if o.tzinfo is None:
o = o.replace(tzinfo=pytz.utc)
return o.isoformat()
# Return the repr for object that json can't encode
logger.warning(
"cannot properly encode in JSON the object %s, " "returned repr is: %r",
type(o),
o,
)
return repr(o)

View file

@ -21,9 +21,9 @@ from moulinette.core import MoulinetteError, MoulinetteValidationError
from moulinette.interfaces import ( from moulinette.interfaces import (
BaseActionsMapParser, BaseActionsMapParser,
ExtendedArgumentParser, ExtendedArgumentParser,
JSONExtendedEncoder,
) )
from moulinette.utils import log from moulinette.utils import log
from moulinette.utils.serialize import JSONExtendedEncoder
from moulinette.utils.text import random_ascii from moulinette.utils.text import random_ascii
logger = log.getLogger("moulinette.interface.api") logger = log.getLogger("moulinette.interface.api")

View file

@ -5,7 +5,7 @@ import sys
import getpass import getpass
import locale import locale
import logging import logging
from argparse import SUPPRESS import argparse
from collections import OrderedDict from collections import OrderedDict
from datetime import date, datetime from datetime import date, datetime
@ -17,6 +17,7 @@ from moulinette.core import MoulinetteError, MoulinetteValidationError
from moulinette.interfaces import ( from moulinette.interfaces import (
BaseActionsMapParser, BaseActionsMapParser,
ExtendedArgumentParser, ExtendedArgumentParser,
JSONExtendedEncoder,
) )
from moulinette.utils import log from moulinette.utils import log
@ -32,17 +33,14 @@ from moulinette.utils import log
# But it display instead: # But it display instead:
# Error: unable to parse arguments 'firewall' because: sequence item 0: expected str instance, NoneType found # Error: unable to parse arguments 'firewall' because: sequence item 0: expected str instance, NoneType found
import argparse
def monkey_get_action_name(argument): def monkey_get_action_name(argument):
if argument is None: if argument is None:
return None return None
elif argument.option_strings: elif argument.option_strings:
return "/".join(argument.option_strings) return "/".join(argument.option_strings)
elif argument.metavar not in (None, SUPPRESS): elif argument.metavar not in (None, argparse.SUPPRESS):
return argument.metavar return argument.metavar
elif argument.dest not in (None, SUPPRESS): elif argument.dest not in (None, argparse.SUPPRESS):
return argument.dest return argument.dest
elif argument.choices: elif argument.choices:
return "{" + ",".join(argument.choices) + "}" return "{" + ",".join(argument.choices) + "}"
@ -307,7 +305,7 @@ class ActionsMapParser(BaseActionsMapParser):
# Append each top parser action to the global group # Append each top parser action to the global group
for action in top_parser._actions: for action in top_parser._actions:
action.dest = SUPPRESS action.dest = argparse.SUPPRESS
self.global_parser._add_action(action) self.global_parser._add_action(action)
# Implement virtual properties # Implement virtual properties
@ -509,8 +507,6 @@ class Interface:
if output_as: if output_as:
if output_as == "json": if output_as == "json":
import json import json
from moulinette.utils.serialize import JSONExtendedEncoder
print(json.dumps(ret, cls=JSONExtendedEncoder)) print(json.dumps(ret, cls=JSONExtendedEncoder))
else: else:
plain_print_dict(ret) plain_print_dict(ret)

View file

@ -1,45 +0,0 @@
import logging
from json.encoder import JSONEncoder
import datetime
logger = logging.getLogger("moulinette.utils.serialize")
# JSON utilities -------------------------------------------------------
class JSONExtendedEncoder(JSONEncoder):
"""Extended JSON encoder
Extend default JSON encoder to recognize more types and classes. It will
never raise an exception if the object can't be encoded and return its repr
instead.
The following objects and types are supported:
- set: converted into list
"""
def default(self, o):
import pytz # Lazy loading, this takes like 3+ sec on a RPi2 ?!
"""Return a serializable object"""
# Convert compatible containers into list
if isinstance(o, set) or (hasattr(o, "__iter__") and hasattr(o, "next")):
return list(o)
# Display the date in its iso format ISO-8601 Internet Profile (RFC 3339)
if isinstance(o, datetime.date):
if o.tzinfo is None:
o = o.replace(tzinfo=pytz.utc)
return o.isoformat()
# Return the repr for object that json can't encode
logger.warning(
"cannot properly encode in JSON the object %s, " "returned repr is: %r",
type(o),
o,
)
return repr(o)

View file

@ -1,5 +1,5 @@
from datetime import datetime as dt from datetime import datetime as dt
from moulinette.utils.serialize import JSONExtendedEncoder from moulinette.interface import JSONExtendedEncoder
def test_json_extended_encoder(caplog): def test_json_extended_encoder(caplog):