Skip to content

Commit

Permalink
Merge pull request #12 from Wiston999/development
Browse files Browse the repository at this point in the history
Merged development into master
  • Loading branch information
Wiston999 committed Mar 28, 2016
2 parents 3ed37b5 + 56fed8f commit bc53283
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 69 deletions.
15 changes: 15 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
engines:
duplication:
enabled: true
config:
languages:
- python
fixme:
enabled: true
radon:
enabled: true
ratings:
paths:
- "**.py"
exclude_paths: []
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ python:
- "2.6"
- "2.7"
# - "3.2"
# - "3.3"
# - "3.4"
# - "3.5"
- "3.3"
- "3.4"
- "3.5"

install: "pip install -r requirements.txt"
# command to run tests
script: python tests.py
script: python tests.py

addons:
code_climate:
repo_token: af84895870b053b268ad69c75b81bd4e3276f33327adc97243e58a64a30ceffa
73 changes: 48 additions & 25 deletions doc/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ We will map the *type* key into a field named *user_type* into our model.

.. code-block:: python
:linenos:
:caption: models.py
:name: models.py
:caption: models1.py
:name: models1.py
from json2py.models import *
Expand All @@ -55,12 +55,12 @@ And we are all done! Now let's request the Github's user info endpoint.
response = requests.get('https://api.github.com/users/wiston999')
my_user = User(response.json())
print my_user.login.value, "'s stats:"
print "id:", my_user.id.value
print "login:", my_user.login.value
print "url:", my_user.url.value
print "type:", my_user.user_type.value
print "site_admin:", my_user.site_admin.value
print (my_user.login.value, "'s stats:")
print ("id:", my_user.id.value)
print ("login:", my_user.login.value)
print ("url:", my_user.url.value)
print ("type:", my_user.user_type.value)
print ("site_admin:", my_user.site_admin.value)
Output after executing this code is

Expand All @@ -87,8 +87,8 @@ already modeled into the previous example, so, let's use a bit of code re-utiliz

.. code-block:: python
:linenos:
:caption: models.py
:name: models.py
:caption: models2.py
:name: models2.py
:emphasize-lines: 8-
class User(NestedField):
Expand Down Expand Up @@ -124,14 +124,14 @@ Let's try these models
response = requests.get('https://api.github.com/repos/wiston999/json2py')
this_repo = Repo(response.json())
print this_repo.name.value, "'s stats:"
print "id:", this_repo.id.value
print "full_name:", this_repo.full_name.value
print "owner:", this_repo.owner.login.value
print "private:", this_repo.is_private.value
print "description:", this_repo.description.value
print "language:", this_repo.language.value
print "default_branch:", this_repo.default_branch.value
print (this_repo.name.value, "'s stats:")
print ("id:", this_repo.id.value)
print ("full_name:", this_repo.full_name.value)
print ("owner:", this_repo.owner.login.value)
print ("private:", this_repo.is_private.value)
print ("description:", this_repo.description.value)
print ("language:", this_repo.language.value)
print ("default_branch:", this_repo.default_branch.value)
Will output

Expand All @@ -155,8 +155,8 @@ a list of repositories, which we have already modeled, so, this should be as sim

.. code-block:: python
:linenos:
:caption: models.py
:name: models.py
:caption: models3.py
:name: models3.py
:emphasize-lines: 19-
class User(NestedField):
Expand Down Expand Up @@ -186,18 +186,17 @@ Everything done! Let's try it
:linenos:
:caption: example3.py
:name: example3.py
:emphasize-lines: 9
import requests
from models import RepoList
response = requests.get('https://api.github.com/users/wiston999/repos')
user_repo_list = RepoList(response.json())
print "wiston999's repositories:"
print ("wiston999's repositories:")
for repo in user_repo_list:
print "Repository name:", repo.name.value, "with id:", repo.id.value, "written in", repo.language.value
print "Repository Owner:", repo.owner.login.value
print '-'*70
print ("Repository name:", repo.name.value, "with id:", repo.id.value, "written in", repo.language.value)
print ("Repository Owner:", repo.owner.login.value)
print ('-'*70)
And the output

Expand Down Expand Up @@ -228,3 +227,27 @@ And the output
Repository name: repos-git with id: 20038280 written in Python
Repository Owner: Wiston999
----------------------------------------------------------------------
Using Python's reserved keywords
--------------------------------

When the need of model JSON or dict keys that are Python's keywords too (like from, in, for, etc.),
one cannot do

.. code-block:: python
class BadKeyword(NestedField):
from = IntegerField()
as it raises :exc:`.SyntaxError`. A workaround to solve this is use the ``name`` parameter
declared in :class:`json2py.models.BaseField`, so the previous can be solved with the following code

.. code-block:: python
class BetterKeyword(NestedField):
from_ = IntegerField(name = 'from')
Once ``name`` parameter is used, the name of variable can be anything distinct to Python's keywords and previous
variable names.
5 changes: 0 additions & 5 deletions doc/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ BooleanField
.. autoclass:: BooleanField
:members:


.. todo::

Document how to access elements in :class:`.NestedField` with same name than Python's reserved keywords.

NestedField
-----------

Expand Down
47 changes: 24 additions & 23 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import print_function
import requests
from json2py.models import *

Expand Down Expand Up @@ -36,38 +37,38 @@ class RepoList(ListField):
response = requests.get('https://api.github.com/users/%s' % github_user)
if response.status_code == 200:
my_user = User(response.json())
print my_user.login.value, "'s stats:"
print "id:", my_user.id.value
print "email:", my_user.email.value
print "full_name:", my_user.full_name.value
print "login:", my_user.login.value
print "url:", my_user.url.value
print "type:", my_user.user_type.value
print "site_admin:", my_user.site_admin.value
print (my_user.login.value, "'s stats:")
print ("id:", my_user.id.value)
print ("email:", my_user.email.value)
print ("full_name:", my_user.full_name.value)
print ("login:", my_user.login.value)
print ("url:", my_user.url.value)
print ("type:", my_user.user_type.value)
print ("site_admin:", my_user.site_admin.value)
else:
print "User response status code", response.status_code
print ("User response status code", response.status_code)

response = requests.get('https://api.github.com/repos/%s/%s' %(github_user, github_repo))
if response.status_code == 200:
this_repo = Repo(response.json())
print this_repo.name.value, "'s stats:"
print "id:", this_repo.id.value
print "full_name:", this_repo.full_name.value
print "owner:", this_repo.owner.login.value
print "private:", this_repo.is_private.value
print "description:", this_repo.description.value
print "language:", this_repo.language.value
print "default_branch:", this_repo.default_branch.value
print (this_repo.name.value, "'s stats:")
print ("id:", this_repo.id.value)
print ("full_name:", this_repo.full_name.value)
print ("owner:", this_repo.owner.login.value)
print ("private:", this_repo.is_private.value)
print ("description:", this_repo.description.value)
print ("language:", this_repo.language.value)
print ("default_branch:", this_repo.default_branch.value)
else:
print "Repo response status code", response.status_code
print ("Repo response status code", response.status_code)

response = requests.get('https://api.github.com/users/%s/repos' % github_user)
if response.status_code == 200:
user_repo_list = RepoList(response.json())
print github_user, "repositories:"
print (github_user, "repositories:")
for repo in user_repo_list:
print "Repository name:", repo.name.value, "with id:", repo.id.value, "written in", repo.language.value
print "Repository Owner:", repo.owner.login.value
print '-'*70
print ("Repository name:", repo.name.value, "with id:", repo.id.value, "written in", repo.language.value)
print ("Repository Owner:", repo.owner.login.value)
print ('-'*70)
else:
print "RepoList response status code", response.status_code
print ("RepoList response status code", response.status_code)
20 changes: 12 additions & 8 deletions json2py/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from past.builtins import basestring
from builtins import int
import json
from dateutil.parser import parse
from datetime import datetime
Expand Down Expand Up @@ -93,7 +95,7 @@ def __init__(self, value = None, name = None, required = True):
super(TextField, self).__init__(value, name, required)
self.value = value

if not isinstance(self.value, (str, unicode)) and self.value is not None:
if not isinstance(self.value, basestring) and self.value is not None:
raise ParseException('TextField cannot parse non string')

def __str__(self):
Expand Down Expand Up @@ -129,7 +131,7 @@ def __init__(self, value = None, name = None, required = True):
super(NumberField, self).__init__(value, name, required)
self.value = value

if not isinstance(self.value, (int, long)) and self.value is not None:
if not isinstance(self.value, int) and self.value is not None:
raise ParseException('IntegerField cannot parse non integer')


Expand All @@ -146,19 +148,20 @@ def __init__(self, value = None, name = None, required = True):
super(NumberField, self).__init__(value, name, required)
self.value = value

if not isinstance(self.value, (float, int, long)) and self.value is not None:
if not isinstance(self.value, (float, int)) and self.value is not None:
raise ParseException('FloatField cannot parse non float')


class NestedField(BaseField):
"""
Class representing a document field in JSON.
:arg value: It is the raw data that is this object will represent once parsed.
:arg name: It has the same meaning as in :class:`.BaseField`
:arg required: It has the same meaning as in :class:`.BaseField`
:raise ParseException: If ``value`` is not a dict nor None
:raise `ParseException`: If ``value`` is not a dict nor None
:note: For use cases and examples refer to :doc:`examples`
"""
def __init__(self, value = None, name = None, required = True):
super(NestedField, self).__setattr__('value', {})
Expand Down Expand Up @@ -190,7 +193,8 @@ def __init__(self, value = None, name = None, required = True):
field = field.__class__(data[key])
else:
field = field.__class__(None)
self.value[reverseLookUp[key]] = field

super(NestedField, self).__getattribute__('value')[reverseLookUp[key]] = field
# setattr(self, reverseLookUp[key], field)

def __setattr__(self, key, value):
Expand Down Expand Up @@ -339,10 +343,10 @@ def __init__(self, value = None, name = None, required = True, formatting = "%Y-
field_type = 'int'

if field_type == 'str':
if not isinstance(value, (str, unicode)) and value is not None:
if not isinstance(value, basestring) and value is not None:
raise ParseException("DateField cannot parse non string with formatting specified '%s'" % self.formatting)
elif field_type == 'int':
if not isinstance(value, (int, long)) and value is not None:
if not isinstance(value, int) and value is not None:
raise ParseException("DateField cannot parse non integer with formatting specified '%s'" % self.formatting)

if value is not None:
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
python-dateutil==2.4.2
python-dateutil==2.4.2
future==0.15.2
9 changes: 6 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

setup(
name = 'json2py',
version = '0.2',
version = '0.3',
packages = ['json2py'],
url = 'https://github.com/Wiston999/json2py',
download_url = 'https://github.com/Wiston999/json2py/tarball/v0.1-beta',
download_url = 'https://github.com/Wiston999/json2py/tarball/v0.3',
license = 'MIT',
author = 'Victor Cabezas',
author_email = 'wiston666@gmail.com',
Expand All @@ -17,6 +17,9 @@
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7'
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5'
]
)
2 changes: 2 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class NoReq(NestedField):

self.assertEqual(NoReq({}).no_req.value, None)

self.assertEqual(NoReq({"no_req": 10}).no_req.value, 10)


class BooleanTest(unittest.TestCase):
def test_value(self):
Expand Down

0 comments on commit bc53283

Please sign in to comment.