Commit 4e16ad73 by Oleksandr Barabash

added jsoner, log, pbkdf2_hmac

parent 76ce2864
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.1 (/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/s1zlibs.iml" filepath="$PROJECT_DIR$/.idea/s1zlibs.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="65d42553-dd76-4359-9c87-e7f5083fe8d6" name="Default" comment="" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="false">
<entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="218">
<caret line="1457" selection-start-line="1457" selection-end-line="1462" selection-end-column="26" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/jsoner/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="183">
<caret line="20" column="40" selection-start-line="20" selection-start-column="40" selection-end-line="20" selection-end-column="40" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="base_serializable.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/jsoner/serializable/base_serializable.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" selection-start-line="6" selection-end-line="6" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="base_field.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/jsoner/fields/base_field.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="11" selection-start-line="4" selection-start-column="11" selection-end-line="4" selection-end-column="11" />
<folding>
<element signature="e#0#38#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="simple_serializer.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/jsoner/serializers/simple_serializer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="136">
<caret line="8" column="6" selection-start-line="8" selection-start-column="6" selection-end-line="8" selection-end-column="6" />
<folding>
<element signature="e#0#38#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/jsoner/fields/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>lock</find>
<find>SerializableField</find>
</findStrings>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/utils/log.py" />
<option value="$PROJECT_DIR$/utils/pbkdf2_hmac.py" />
<option value="$PROJECT_DIR$/jsoner/decorators.py" />
<option value="$PROJECT_DIR$/jsoner/serializers/base_serializer.py" />
<option value="$PROJECT_DIR$/jsoner/serializers/__init__.py" />
<option value="$PROJECT_DIR$/jsoner/serializers/simple_serializer.py" />
<option value="$PROJECT_DIR$/jsoner/fields/__init__.py" />
<option value="$PROJECT_DIR$/jsoner/fields/simple_field.py" />
<option value="$PROJECT_DIR$/jsoner/serializable/base_serializable.py" />
<option value="$PROJECT_DIR$/jsoner/__init__.py" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="NodePackageJsonFileManager">
<packageJsonPaths />
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="y" value="23" />
<option name="width" value="1440" />
<option name="height" value="877" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="s1zlibs" type="b2602c69:ProjectViewProjectNode" />
<item name="s1zlibs" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="s1zlibs" type="b2602c69:ProjectViewProjectNode" />
<item name="s1zlibs" type="462c0819:PsiDirectoryNode" />
<item name="jsoner" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="s1zlibs" type="b2602c69:ProjectViewProjectNode" />
<item name="s1zlibs" type="462c0819:PsiDirectoryNode" />
<item name="jsoner" type="462c0819:PsiDirectoryNode" />
<item name="serializable" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/jsoner" />
<recent name="$PROJECT_DIR$/utils" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="65d42553-dd76-4359-9c87-e7f5083fe8d6" name="Default" comment="" />
<created>1546539823731</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1546539823731</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="23" width="1440" height="877" extended-state="6" />
<editor active="true" />
<layout>
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Database Changes" show_stripe_button="false" />
<window_info anchor="bottom" id="Run" order="2" />
<window_info anchor="bottom" id="Version Control" show_stripe_button="false" />
<window_info anchor="bottom" id="Python Console" />
<window_info anchor="bottom" id="Terminal" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.25" />
<window_info anchor="bottom" id="Docker" show_stripe_button="false" />
<window_info anchor="right" id="Database" />
<window_info anchor="right" id="SciView" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info id="Favorites" side_tool="true" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="editorHistoryManager">
<entry file="file://$APPLICATION_HOME_DIR$/helpers/typeshed/stdlib/2and3/threading.pyi">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/utils/pbkdf2_hmac.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="12" lean-forward="true" selection-start-line="12" selection-end-line="12" />
<folding>
<element signature="e#46#85#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/utils/log.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="92">
<caret line="49" column="39" selection-start-line="49" selection-start-column="39" selection-end-line="49" selection-end-column="39" />
<folding>
<element signature="e#46#85#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/functions.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/decorators.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret lean-forward="true" />
</state>
</provider>
</entry>
<entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="218">
<caret line="1457" selection-start-line="1457" selection-end-line="1462" selection-end-column="26" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/serializers/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/serializers/base_serializer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="11" column="41" selection-start-line="11" selection-start-column="41" selection-end-line="11" selection-end-column="41" />
<folding>
<element signature="e#0#38#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/fields/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/serializers/simple_serializer.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="136">
<caret line="8" column="6" selection-start-line="8" selection-start-column="6" selection-end-line="8" selection-end-column="6" />
<folding>
<element signature="e#0#38#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/fields/base_field.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="11" selection-start-line="4" selection-start-column="11" selection-end-line="4" selection-end-column="11" />
<folding>
<element signature="e#0#38#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/serializable/base_serializable.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" selection-start-line="6" selection-end-line="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/jsoner/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="183">
<caret line="20" column="40" selection-start-line="20" selection-start-column="40" selection-end-line="20" selection-end-column="40" />
</state>
</provider>
</entry>
</component>
</project>
\ No newline at end of file
from __future__ import absolute_import
try:
import simplejson as json
except ImportError as e:
import json
from .fields.base_field import BaseField
from .functions import jsonize_str
from .functions import pythonize_str
from .decorators import with_metaclass
TAG = "Serializable"
_field_name = "_jsoner_data"
class MetaSerializable(type):
def __new__(cls, name, bases, attrs):
jsoner_field = attrs.pop(_field_name, {})
new_cls = super(MetaSerializable, cls).__new__(cls, name, bases, attrs)
for base in bases:
if hasattr(base, _field_name):
jsoner_field.update(getattr(base, _field_name, {}))
for k, v in attrs.items():
if isinstance(v, BaseField):
# Here's the place where the magic comes!
jsoner_field[k] = v
setattr(new_cls, k, None)
setattr(new_cls, _field_name, jsoner_field)
return new_cls
def __call__(cls, *args, **kwargs):
return type.__call__(cls, *args, **kwargs)
@with_metaclass(MetaSerializable)
class Serializable(object):
def loads(self, data):
# type: () -> self
loaded = json.loads(data)
if not isinstance(loaded, dict):
raise AttributeError("data is not dict instance: '{}'".format(
type(data).__name__
))
for field_name, field in getattr(self, _field_name, {}).items():
if isinstance(field, BaseField):
j_field_name = pythonize_str(field_name) if field.jsonize else \
field_name
j_value = loaded.get(j_field_name, None)
loaded_value = field.loads(j_value)
setattr(self, field_name, loaded_value)
return self
def dumps(self):
# type: () -> self
dumped = dict()
for field_name, field in getattr(self, _field_name, {}).items():
if isinstance(field, BaseField):
value = getattr(self, field_name, None)
j_field_name = jsonize_str(field_name) if field.jsonize else \
field_name
j_value = field.dumps(value)
dumped[j_field_name] = j_value
return json.dumps(dumped)
def with_metaclass(mcls):
def decorator(cls):
body = vars(cls).copy()
body.pop('__dict__', None)
body.pop('__weakref__', None)
return mcls(cls.__name__, cls.__bases__, body)
return decorator
from __future__ import absolute_import
from ..serializers.simple_serializer import SimpleSerializer
TAG = "BaseField"
class BaseField(object):
serializer = None
null = None
jsonize = None
def __init__(self, value_type, serializer=SimpleSerializer, null=True,
jsonize=True):
"""
:param value_type: type of the value we serialize
:type value_type: any
:param serializer: Serializer class
:type serializer: any
:param null: Do we need to send null if None is set
:type null: bool
:param jsonize: Should we convert "test_name" to "testName" and back
:type jsonize: bool
"""
self.serializer = serializer(value_type)
self.null = null
self.jsonize = jsonize
def check_null(self, value):
if value is None and self.null is not True:
raise AttributeError("Value has to be not null: {}".format(value))
return value
def loads(self, value):
return self.serializer.loads(value)
def dumps(self, value):
self.check_null(value)
return self.serializer.dumps(value)
def pythonize_str(data):
# Converts name to a python style names:
# simpleTestValue -> simple_test_value
name_len = len(data)
new_data = ""
for i in range(name_len):
c = data[i]
if c.isupper():
new_data += "_" + c.lower()
else:
new_data += c
return new_data
def jsonize_str(data):
# Converts data to a json style names:
# simple_test_value -> simpleTestValue
if data.find("_") == -1:
return data
name_len = len(data)
new_data = ""
for i in range(name_len):
c = data[i]
if c == "_":
continue
elif i == 0 and c.isalpha():
new_data += c
elif c.isalpha():
if data[i - 1] == "_":
new_data += c.upper()
else:
new_data += c
return new_data
from __future__ import absolute_import
_field_name = "_jsoner_data"
from __future__ import absolute_import
from abc import ABCMeta
from abc import abstractmethod
from ..decorators import with_metaclass
@with_metaclass(ABCMeta)
class BaseSerializer(object):
@abstractmethod
def loads(self, data):
# type: (bytes) -> BaseSerializer
raise NotImplementedError("IMPL ME")
@abstractmethod
def dumps(self, data):
# type: (any) -> bytes
raise NotImplementedError("IMPL ME")
\ No newline at end of file
from __future__ import absolute_import
from utils.log import Log
from .base_serializer import BaseSerializer
TAG = "SimpleSerializer"
class SimpleSerializer(BaseSerializer):
value_is_list = None
value_type = None
handle_types = (str, bytes, int, float, bool)
def __init__(self, value_type):
self.value_is_list, self.value_type = self.get_value_type(value_type)
Log.d(TAG, "value_is_list, value_type: {},{}".format(
self.value_is_list, self.value_type
))
@staticmethod
def raise_value_error(value):
raise AttributeError("Could not handle value: {}".format(value))
def get_value_type(self, value_type):
# If the value type is an array
if isinstance(value_type, list) and len(value_type) == 1:
return True, value_type[0]
# Check if this is a simple value
elif value_type in self.handle_types:
return False, value_type
return self.raise_value_error(value_type)
def check_type(self, values):
# type: (list) -> list
dumped = list()
for raw_data in values:
if not isinstance(raw_data, self.value_type):
self.raise_value_error(raw_data)
dumped.append(raw_data)
return dumped
def loads(self, value):
if not self.value_is_list and not isinstance(value, list):
self.check_type([value])
return value
elif self.value_is_list and isinstance(value, list):
return self.check_type(value)
return self.raise_value_error(value)
def dumps(self, value):
if not self.value_is_list and not isinstance(value, list):
self.check_type([value])
return value
elif self.value_is_list and isinstance(value, list):
return self.check_type(value)
return self.raise_value_error(value)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import traceback
import logging
try:
import threading
except ImportError: #pragma: no cover
threading = None
if threading:
_lock = threading.RLock()
else: #pragma: no cover
_lock = None
def _acquireLock():
"""
Acquire the module-level lock for serializing access to shared data.
This should be released with _releaseLock().
"""
if _lock:
_lock.acquire()
def _releaseLock():
"""
Release the module-level lock acquired by calling _acquireLock().
"""
if _lock:
_lock.release()
class Log(object):
logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
tags = dict()
@staticmethod
def get_or_create_tag(tag):
# TODO(s1z): Finish this please
_acquireLock()
try:
if tag in Log.tags:
return Log.tags[tag]
finally:
_releaseLock()
@staticmethod
def log(level, tag, message, ex):
if ex is not None:
# exc_type, exc_value, exc_traceback = sys.exc_info()
message = "%s\n%s" % (message, traceback.format_exc())
msg = "{}::{}".format(tag, message)
Log.logger.log(level, msg)
@staticmethod
def v(tag, message, ex=None):
""" Thers is no VERBOSE in python logging we use DEBUG """
return Log.log(logging.DEBUG, tag, message, ex)
@staticmethod
def d(tag, message, ex=None):
return Log.log(logging.DEBUG, tag, message, ex)
@staticmethod
def i(tag, message, ex=None):
return Log.log(logging.INFO, tag, message, ex)
@staticmethod
def w(tag, message, ex=None):
return Log.log(logging.WARN, tag, message, ex)
@staticmethod
def e(tag, message, ex=None):
return Log.log(logging.ERROR, tag, message, ex)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import print_function
from hashlib import new
try:
range = xrange
except NameError:
buffer = memoryview
try:
# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
from _hashlib import pbkdf2_hmac
except ImportError:
import binascii
import struct
_trans_5C = bytes(bytearray([x ^ 0x5C for x in range(256)]))
_trans_36 = bytes(bytearray([x ^ 0x36 for x in range(256)]))
def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
"""Password based key derivation function 2 (PKCS #5 v2.0)
This Python implementations based on the hmac module about as fast
as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
for long passwords.
"""
if not isinstance(hash_name, str):
raise TypeError(hash_name)
if not isinstance(password, (bytes, bytearray)):
raise TypeError("a bytes-like object is required, not '{}'".format(
type(password).__name__
))
if not isinstance(salt, (bytes, bytearray)):
raise TypeError("a bytes-like object is required, not '{}'".format(
type(salt).__name__
))
# Fast inline HMAC implementation
inner = new(hash_name)
outer = new(hash_name)
blocksize = getattr(inner, 'block_size', 64)
if len(password) > blocksize:
password = new(hash_name, password).digest()
password = password + b'\x00' * (blocksize - len(password))
inner.update(password.translate(_trans_36))
outer.update(password.translate(_trans_5C))
def prf(msg, inner=inner, outer=outer):
# PBKDF2_HMAC uses the password as key. We can re-use the same
# digest objects and just update copies to skip initialization.
icpy = inner.copy()
ocpy = outer.copy()
icpy.update(msg)
ocpy.update(icpy.digest())
return ocpy.digest()
if iterations < 1:
raise ValueError(iterations)
if dklen is None:
dklen = outer.digest_size
if dklen < 1:
raise ValueError(dklen)
hex_format_string = "%%0%ix" % (new(hash_name).digest_size * 2)
dkey = b''
loop = 1
while len(dkey) < dklen:
prev = prf(salt + struct.pack(b'>I', loop))
rkey = int(binascii.hexlify(prev), 16)
for i in range(iterations - 1):
prev = prf(prev)
rkey ^= int(binascii.hexlify(prev), 16)
loop += 1
dkey += binascii.unhexlify(hex_format_string % rkey)
return dkey[:dklen]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment