Skip to content

Commit

Permalink
Merge remote-tracking branch 'github/develop' into develop
Browse files Browse the repository at this point in the history
Conflicts:
	simplekit/objson/dynamic_class.py
  • Loading branch information
benjamin.c.yan committed Jan 19, 2016
2 parents 0cb0075 + 90b1dba commit d696cf9
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 66 deletions.
12 changes: 8 additions & 4 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
History
======
0.0.5
--------------
1. refactor objson module
2. support for add attributes dynamically

0.0.4
---------
--------------
1. add documents
2. fix some bug

0.0.3
------
--------------
1. use `type` factory instead of just compile code
2. add new unittest
3. fix dump bug
4. rename project name to simplekit
5. fix dump list object

0.0.2
------
--------------
1. change dynamic class from dict to object
2. escape keyword properties, add 'm' prefix.

0.0.1
-----
--------------
1. init project
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ test:
@rm -vf .coverage coverage.xml
@$(COVER) run -m unittest discover --start-directory tests --pattern *_test.py
@$(COVER) html
@python -m webbrowser -t "$(CWD)/htmlcov/index.html"
# @python -m webbrowser -t "$(CWD)/htmlcov/index.html"

clean:
@rm -vf .coverage
Expand Down
Empty file added docs/_static/README.md
Empty file.
4 changes: 2 additions & 2 deletions docs/objson.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ the property name is start with digit,

the dolphin libs will escape the property, add prefix string "m".

and also, property contains any other character which is not alpha, digit and ``_``(underscore)
will replace to ``_``(underscore).
and also, property contains any other character which is not alpha, digit and ``_`` (underscore)
will replace to ``_`` (underscore).

For example:

Expand Down
2 changes: 1 addition & 1 deletion simplekit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__author__ = 'benjamin.c.yan'
__version__ = "0.0.4"
__version__ = "0.0.5"
10 changes: 7 additions & 3 deletions simplekit/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,25 +271,29 @@ def db_full_path(self):

def get_namespace(self, namespace, lowercase=True, trim_namespace=True):
"""Returns a dictionary containing a subset of configuration options
that match the specified namespace/prefix. Example usage:
that match the specified namespace/prefix. Example usage::
app.config['IMAGE_STORE_TYPE']='fs'
app.config['IMAGE_STORE_PATH']='/var/app/images'
app.config['IMAGE_STORE_BASE_URL']='http://img.website.com'
The result dictionary `image_store` would look like:
The result dictionary `image_store` would look like::
{
'type': 'fs',
'path': '/var/app/images',
'base_url':'http://image.website.com'
}
This is often useful when configuration options map directly to keyword arguments in functions or class constructors.
This is often useful when configuration options map directly to keyword arguments in functions
or class constructors.
:param namespace: a configuration namespace
:param lowercase: a flag indicating if the keys of the resulting
dictionary should be lowercase
:param trim_namespace: a flag indicating if the keys of the resulting
dictionary should not include the namespace
:return: a dict instance
"""
rv = {}
for key, value in six.iteritems(self):
Expand Down
14 changes: 4 additions & 10 deletions simplekit/objson/dolphin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
__author__ = 'benjamin.c.yan'

import json
import itertools

from .dynamic_class import make_dynamic_class


_knapsack = {}

_random_seed = 0
seed = itertools.count(1)


def object2dict(obj):
Expand All @@ -18,7 +19,7 @@ def object2dict(obj):


def object_hook(obj):
unique_id = _unique(obj)
unique_id = tuple((key, type(obj[key])) for key in sorted(obj.keys()))
if unique_id in _knapsack:
dynamic_class = _knapsack[unique_id]
else:
Expand All @@ -30,14 +31,7 @@ def object_hook(obj):


def _random_name():
global _random_seed
_random_seed += 1
return 'Dolphin_%d' % _random_seed


def _unique(obj):
tmp = tuple([(key, type(obj[key])) for key in sorted(obj.keys())])
return hash(tmp)
return 'Dolphin_%d' % next(seed)


def dumps(obj, *args, **kwargs):
Expand Down
78 changes: 42 additions & 36 deletions simplekit/objson/dynamic_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ def _getter(item):
return _getter


def _dynamic__init(self, kv):
self._data = dict()
self._data.update(kv)
def _dynamic__init(self, kv=None):
# self._data = dict()
if kv is None:
kv = dict()
self.__dict__.update(kv)


def _dynamic__setitem(self, key, value):
self._data[key] = value
self.__dict__[key] = value


def _property(name):
Expand All @@ -50,34 +52,39 @@ def make_dynamic_class(typename, field_names):
template to define a dynamic class, instead of, I use the :func:`type` factory
function.
Class prototype definition:
>>> class JsonObject(object):
>>> __identifier__ = "dolphin"
>>>
>>> __slots__ = ('name', 'age')
>>>
>>> _data = dict()
>>>
>>> def __init__(self, kv):
>>> self._data.update(kv)
>>>
>>> def __getitem__(self, key):
>>> return self._data.get(key)
>>>
>>> def __setitem__(self, key, value):
>>> self._data[key] = value
>>>
>>> def __iter__(self):
>>> return self._data.__iter__()
>>>
>>> def __repr__(self):
>>> keys = sorted(self._data.keys())
>>> text = ', '.join(["%s=%r" % (key, self[key]) for key in keys])
>>> return '{%s}' % text
>>>
>>> name = property(_item_getter('name'), _item_setter('name'))
>>> age = property(_item_getter('age'), _item_setter('age'))
Class prototype definition ::
class JsonObject(object):
__identifier__ = "dolphin"
def __init__(self, kv=None):
if kv is None:
kv = dict()
self.__dict__.update(kv)
def __getitem__(self, key):
return self.__dict__.get(key)
def __setitem__(self, key, value):
self.__dict__[key] = value
def __iter__(self):
return iter(self.__dict__)
def __repr__(self):
keys = sorted(self.__dict__.keys())
text = ', '.join(["%s=%r" % (key, self[key]) for key in keys])
return '{%s}' % text
name=_property('name')
Basic Usage ::
from objson import make_dynamic_class, dumps
Entity = make_dynamic_class('Entity', 'name, sex, age')
entity = Entity()
entity.name, entity.sex, entity.age = 'benjamin', 'male', 21
dumps(entity)
:param typename: dynamic class's name
:param field_names: a string :class:`list` and a field name string which separated by comma,
Expand All @@ -94,14 +101,13 @@ def make_dynamic_class(typename, field_names):
attr = dict((safe_name, _property(name)) for name, safe_name in zip(field_names, safe_fields_names))
attr['__doc__'] = typename
attr['__identifier__'] = "dolphin"
attr['__slots__'] = tuple(['_data'] + safe_fields_names)
attr['__init__'] = _dynamic__init
attr['__getitem__'] = lambda self, key: self._data.get(key)
attr['__getitem__'] = lambda self, key: self.__dict__.get(key)
attr['__setitem__'] = _dynamic__setitem
attr['__iter__'] = lambda self: iter(self._data)
attr['__iter__'] = lambda self: iter(self.__dict__)
attr['__repr__'] = lambda self: "{%s}" % (', '.join([
"%s=%r" % (key, self[key]) for key in
sorted(self._data.keys())
sorted(self.__dict__.keys())
]))

return type(typename, (object,), attr)
27 changes: 19 additions & 8 deletions simplekit/threading/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,28 @@ class StoppableThread(threading.Thread):
def __init__(self, daemon=True, group=None, target=None, name=None, args=(), kwargs={}):
super(StoppableThread, self).__init__(group, target, name, args, kwargs)
self.daemon = daemon
self.__stop_event = threading.Event()
self._stopped_event = threading.Event()

def run(self):
while not self.__stop_event.is_set():
self.process()

def process(self):
raise NotImplementedError("please override it")
def start(self):
self.on_thread_start()
threading.Thread.start(self)

def stop(self):
self.__stop_event.set()
self._stop_event.set()
self.on_thread_stop()

@property
def stopped_event(self):
return self._stopped_event

def should_keep_running(self):
return not self._stopped_event.is_set()

def on_thread_stop(self):
pass

def on_thread_start(self):
pass


class LockMixin(object):
Expand Down
2 changes: 1 addition & 1 deletion tests/objson2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ class Dolphin2TestCase(unittest.TestCase):
def test_multi_object(self):
text = r'[{"name":"benjamin"}, {"name": "wendy"}]'
persons = simplekit.objson.loads(text)
persons = sorted(persons, lambda x,y: x.name < y.name)
persons = sorted(persons, lambda x, y: x.name < y.name)
self.assertEqual(u"benjamin", persons[0].name)
self.assertEqual(u"wendy", persons[1].name)

0 comments on commit d696cf9

Please sign in to comment.