Skip to content

Commit

Permalink
CORE-25484 Merge changes from django-tastypie 0.12.2 (#11)
Browse files Browse the repository at this point in the history
Merged commits from the original repo for v0.12.2 tag.

Note: I am going to squash it because I want to keep fork history simpler and to be able to track our own changes. And because I hope that eventually we will get rid of this fork (or even tastypie itself) at all. If you need an actual history - well, sorry.

Original commit messages:

* Get user model and username field in a more lazy way

User model will not be ready at import time

Signed-off-by: Ilya Baryshev <baryshev@gmail.com>

* Django 1.7: migrations

We're keeping old migrations in south_migrations folder to
be backwards-compatible with Django<1.7 and South>=1.0

* Django 1.7: Explicit fixtures in tests

Using of initial_data in tests is problematic due to new app loading mechanism.
Because initial_data fixtures is deprecated in favor of migrations, initial_data
fixtures are renamed (to avoid confusion).
They're explicitly specified in testcases.

* Django 1.7: Lazy loading of User model in management command

After app loading change, User model can no longer be referenced
while app registry is not populated.

This commit completes work in c7aa6c8

* Django 1.7: Fix ApiAccess __unicode__ for py3

* Django 1.7: Fix customuser tests

Due to app loading changes app_label is no longer effective,
so CustomUser model is redefined in tests.
Fixture name is changed to avoid collision with contrib.auth fixture

* Django 1.7: Update tox config

Update Django and django-oauth-plus versions

* Django 1.7: Minor testsuite fixes

* RuntimeError in related_resource, due to model name conflict
* ValueError when assigning to non-nullable field
* Add explicit MIDDLEWARE_CLASSES to avoid checks framework warnings

* Django 1.7: Fix PutListNestResouceValidationTestCase

Attribute 'pk' is ignored, use 'id' instead.
Due to non-monotonic autoincrement in sqlite prior 1.7 test was passing:
both notes were deleted and created anew (pk were not taken into account,
they just "fortunately" matched pks of newley created models).

* Fix for issue django-tastypie#955

* Added test case for the fix

* Removed incorrect import

* Django 1.7: Update tox to latest Django release

* Fixed test requirement for PyYAML. Thanks to AndrewGrossman for the report!

* find resource name using rfind

this fixes a bug where app name and resource name are the same.
/projects/api/v1/projects/1/ should return projects/1/ not projects/api/v1/projects/1/

* make sure we throw exception if not found

* add test

* Added release notes for v0.12.0.

* Bumped to 0.12.0!

* Starting next dev cycle.

* Enable syntax highlighting in README

* Update current version in README.rst

* Added 0.12.1 release notes.

* Bumped to v0.12.1! (posthumously, since I tagged the wrong commit)

* Starting the next dev cycle.

* pep8

* add failing test for prefetch_related resources

* update test

* fix bug by invalidating prefetch cache

* Update python3.rst

simple change from "Tastpie" to "Tastypie".

* Update serialization.rst

fixed typo

* Added my name to the AUTHORS file for the bug fix django-tastypie#955

* Django 1.8 compatibility

* Small optimization of `extract_credentials` method

Getting the header value for key `HTTP_AUTHORIZATION` only once for this method

* Django 1.8: requires SITE_ID in settings

* Django 1.8: update tarball location for 1.8

* Django 1.8: fixed core tests

* Django 1.8: fixed basic tests

* Django 1.8: fix for minor change in unset attributes of model objects

* Django 1.8: update travis config for one more env, disallow 1.7 and 1.8 failures

* Django 1.8: fixed related_resource tests.  I have no idea what I am doing.

* Django 1.8: whoops, no such env as 1.8+py2.6

* Django 1.8: removing not-implemented complex tests which break due to importing deleted comments app

* Last traces of complex.tests

* PUT response code correction

See commit for details

* Update PUT response codes

See commit for details: django-tastypie@abc0bef

* Update to django 1.8b1

* Changed html_theme to "classic" (from "default") to prevent Sphinx build error

* Update testenvs to use official Django 1.8 release

* Replace with python importlib 

Replace django.utils.importlib with python importlib 
"Warning: django.utils.importlib will be removed in Django 1.9"

* Replace with python importlib

Fix
Warning: django.utils.importlib will be removed in Django 1.9.

* Pinning version of mock as 1.1.0 and later no longer support python 2.6

Co-authored-by: Stefan Wehrmeyer <mail@stefanwehrmeyer.com>
Co-authored-by: Ilya Baryshev <baryshev@gmail.com>
Co-authored-by: harishn_knowlarity <harish.srinivas@eng.knowlarity.com>
Co-authored-by: harishn_knowlarity <me.harishn@gmail.com>
Co-authored-by: Daniel Lindsley <daniel@toastdriven.com>
Co-authored-by: Sam Kuehn <samkuehn@gmail.com>
Co-authored-by: Corey Farwell <coreyf@rwell.org>
Co-authored-by: Chris Adams <chris@improbable.org>
Co-authored-by: Jann Kleen <jann.kleen@freshx.de>
Co-authored-by: Eric Theise <erictheise@gmail.com>
Co-authored-by: Matthew Crowson <matthew.d.crowson@gmail.com>
Co-authored-by: George Dorn <georgedorn@gmail.com>
Co-authored-by: Willem Bult <willem.bult@gmail.com>
Co-authored-by: Chewey <prosto-chewey@users.noreply.github.com>
Co-authored-by: Seán Hayes <gasphynx@gmail.com>
Co-authored-by: Simon Kelly <skelly@dimagi.com>
Co-authored-by: Max Naude <maxnaude@gmail.com>
Co-authored-by: Renjith Thankachan <mail3renjith@gmail.com>
Co-authored-by: Sam Thompson <sam.thompson@buildingenergy.com>
  • Loading branch information
20 people committed May 5, 2020
1 parent 0a0ae1c commit 8fb26f4
Show file tree
Hide file tree
Showing 60 changed files with 547 additions and 622 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Expand Up @@ -10,15 +10,17 @@ env:
- DJANGO_VERSION=1.5
- DJANGO_VERSION=1.6
- DJANGO_VERSION=1.7
- DJANGO_VERSION=1.8
- DJANGO_VERSION=dev

matrix:
allow_failures:
- env: DJANGO_VERSION=dev
- env: DJANGO_VERSION=1.7
exclude:
- env: DJANGO_VERSION=dev
python: "2.6"
- env: DJANGO_VERSION=1.8
python: "2.6"
- env: DJANGO_VERSION=1.7
python: "2.6"

Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -84,6 +84,7 @@ Contributors:
* Revolution Systems & The Python Software Foundation for funding a significant portion of the port to Python 3!
* tunix for a patch related to Tastypie's timezone-aware dates.
* Steven Davidson (damycra) for a documentation patch.
* Harish Srinivas for a minor bug fix that raises an exception if a given related resource is none.


Thanks to Tav for providing validate_jsonp.py, placed in public domain.
Expand Down
6 changes: 4 additions & 2 deletions README.rst
Expand Up @@ -4,7 +4,7 @@ django-tastypie

Creating delicious APIs for Django apps since 2010.

Currently in beta (v0.11.4-dev) but being used actively in production on several
Currently in beta (v0.12.3-dev) but being used actively in production on several
sites.


Expand Down Expand Up @@ -34,7 +34,9 @@ Optional
What's It Look Like?
====================

A basic example looks like::
A basic example looks like:

.. code:: python
# myapp/api.py
# ============
Expand Down
6 changes: 3 additions & 3 deletions docs/conf.py
Expand Up @@ -45,9 +45,9 @@
# built documents.
#
# The short X.Y version.
version = '0.11.9'
version = '0.12.3'
# The full version, including alpha/beta/rc tags.
release = '0.11.9-dev'
release = '0.12.3-dev'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down Expand Up @@ -91,7 +91,7 @@

# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
html_theme = 'classic'

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
Expand Down
2 changes: 1 addition & 1 deletion docs/python3.rst
Expand Up @@ -7,7 +7,7 @@ Python 3 Support
As of Tastypie v0.10.0, it has been ported to support both Python 2 & Python 3
within the same codebase. This builds on top of what `six`_ & `Django`_ provide.

No changes are required for anyone running an existing Tastpie
No changes are required for anyone running an existing Tastypie
installation. The API is completely backward-compatible, so you should be able
to run your existing software without modification.

Expand Down
8 changes: 8 additions & 0 deletions docs/release_notes/index.rst
Expand Up @@ -4,6 +4,14 @@ Release Notes
.. toctree::
:maxdepth: 1

v0.12.3-dev
v0.12.1
v0.12.0
v0.11.9-dev
v0.11.8-dev
v0.11.7-dev
v0.11.6-dev
v0.11.5-dev
v0.11.1
v0.11.0
v0.10.0
Expand Down
39 changes: 39 additions & 0 deletions docs/release_notes/v0.12.0.rst
@@ -0,0 +1,39 @@
v0.12.0
=======

:date: 2014-09-11

This release adds official support for both Django 1.7, as well as
several bugfixes.

.. warning::

If you were previously relying on importing the ``User`` model from
``tastypie.compat``, this import will no longer work correctly. This was
removed due to the way app-loading works in Django 1.7 & no great solution
for dodging this issue exists.

If you were using either of::

from tastypie.compat import User
from tastypie.compat import username_field

Please update your code as follows::

from tastypie.compat import get_user_model
from tastypie.compat import get_username_field


Bugfixes
--------

* Drastic reworking of the test suite. (SHA: 95f57f7)
* Fixed Travis to run Python 3.4 tests. (SHA: 7af528c)
* Fixed a bug where URLs would be incorrectly handled if the ``api_name`` &
``resource_name`` were the same. (SHA: fd55aa3)
* Fixed a test requirement for PyYAML. (SHA: b4f6531)
* Added support for Django 1.7. (SHA: 7881bb6)
* Documentation updates:

* Fixed header in ``tools.rst``. (SHA: f8af772)
* Fixed header in ``resources.rst``. (SHA: 9508cbf)
7 changes: 7 additions & 0 deletions docs/release_notes/v0.12.1.rst
@@ -0,0 +1,7 @@
v0.12.1
=======

:date: 2014-10-22

This release is a small bugfix release, specifically to remove accidentally
added files in the Wheel release.
15 changes: 15 additions & 0 deletions docs/release_notes/v0.12.3-dev.rst
@@ -0,0 +1,15 @@
v0.12.3-dev
===========

:date: 2020-05-05

Fork is upgraded to v0.12.2 from mainstream.

Custom fixes, that are still included:
* Deepcopy performance issue fix: https://github.com/RevelSystems/django-tastypie/commit/ece89b244950608723207dd48837a1547dd45cd2
* Fix for invalid decimal strings: https://github.com/RevelSystems/django-tastypie/pull/1
* `importlib` import fix: https://github.com/RevelSystems/django-tastypie/pull/4
* Fix for `django.core.cache.get_cache` import: https://github.com/RevelSystems/django-tastypie/pull/5
* Copy of `django.utils.http.same_origin`: https://github.com/RevelSystems/django-tastypie/pull/6
* Port of fix for `skip_errors=True` in related fields: https://github.com/RevelSystems/django-tastypie/pull/8
* Fix usages of the deprecated `django.conf.urls.patterns`: https://github.com/RevelSystems/django-tastypie/pull/9 and https://github.com/RevelSystems/django-tastypie/pull/10
2 changes: 1 addition & 1 deletion docs/release_notes/v0.9.16.rst
Expand Up @@ -25,7 +25,7 @@ Bugfixes
* Fixed test case to no longer require a defined object class. (SHA: d8e250f)
* Fixed the signature on ``dehydrate`` in the GIS resource class. (SHA: f724919)
* Fixed a bug involving updating foreign relations on create. (SHA: 50a6741)
* Changed the PUT response code (with ``always_return_data = True``) to 202.
* Changed the PUT response code (with ``always_return_data = True``) from 202 to 200.
(SHA: abc0bef)
* Documentation updates:

Expand Down
6 changes: 3 additions & 3 deletions docs/resources.rst
Expand Up @@ -1418,7 +1418,7 @@ with the provided the data to create the new collection.
Return ``HttpNoContent`` (204 No Content) if
``Meta.always_return_data = False`` (default).

Return ``HttpAccepted`` (202 Accepted) if
Return ``HttpAccepted`` (200 OK) if
``Meta.always_return_data = True``.

``put_detail``
Expand All @@ -1440,8 +1440,8 @@ If an existing resource is modified and
``Meta.always_return_data = False`` (default), return ``HttpNoContent``
(204 No Content).
If an existing resource is modified and
``Meta.always_return_data = True``, return ``HttpAccepted`` (202
Accepted).
``Meta.always_return_data = True``, return ``HttpAccepted`` (200
OK).

``post_list``
-------------
Expand Down
2 changes: 1 addition & 1 deletion docs/serialization.rst
Expand Up @@ -45,7 +45,7 @@ The default ``Serializer`` supports the following formats:
* plist (see http://explorapp.com/biplist/)

Not everyone wants to install or support all the serialization options. If you
would list to customize the list of supported formats for your entire site
would like to customize the list of supported formats for your entire site
the :ref:`TASTYPIE_DEFAULT_FORMATS setting <settings.TASTYPIE_DEFAULT_FORMATS>`
allows you to set the default format list site-wide.

Expand Down
5 changes: 3 additions & 2 deletions setup.py
Expand Up @@ -10,7 +10,7 @@

setup(
name='django-tastypie',
version='0.11.9-dev',
version='0.12.3-dev',
description='A flexible & capable API layer for Django.',
author='Daniel Lindsley',
author_email='daniel@toastdriven.com',
Expand All @@ -21,6 +21,7 @@
'tastypie.utils',
'tastypie.management',
'tastypie.management.commands',
'tastypie.south_migrations',
'tastypie.migrations',
'tastypie.contrib',
'tastypie.contrib.gis',
Expand All @@ -38,7 +39,7 @@
'python-mimeparse >= 0.1.4',
'python-dateutil >= 1.5, != 2.0',
],
tests_require=['mock', 'PyYAMP', 'lxml', 'defusedxml'],
tests_require=['mock', 'PyYAML', 'lxml', 'defusedxml'],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Web Environment',
Expand Down
2 changes: 1 addition & 1 deletion tastypie/__init__.py
Expand Up @@ -2,4 +2,4 @@


__author__ = 'Daniel Lindsley & the Tastypie core team'
__version__ = (0, 11, 9, 'dev')
__version__ = (0, 12, 3, 'dev')
21 changes: 12 additions & 9 deletions tastypie/authentication.py
Expand Up @@ -11,7 +11,7 @@
from django.utils.six.moves.urllib.parse import urlparse
from django.utils.translation import ugettext as _
from tastypie.http import HttpUnauthorized
from tastypie.compat import User, username_field
from tastypie.compat import get_user_model, get_username_field

try:
from hashlib import sha1
Expand Down Expand Up @@ -177,12 +177,9 @@ def _unauthorized(self):
return HttpUnauthorized()

def extract_credentials(self, request):
if request.META.get('HTTP_AUTHORIZATION') and request.META['HTTP_AUTHORIZATION'].lower().startswith('apikey '):
(auth_type, data) = request.META['HTTP_AUTHORIZATION'].split()

if auth_type.lower() != 'apikey':
raise ValueError("Incorrect authorization header.")

authorization = request.META.get('HTTP_AUTHORIZATION', '')
if authorization and authorization.lower().startswith('apikey '):
auth_type, data = authorization.split()
username, api_key = data.split(':', 1)
else:
username = request.GET.get('username') or request.POST.get('username')
Expand All @@ -197,7 +194,6 @@ def is_authenticated(self, request, **kwargs):
Should return either ``True`` if allowed, ``False`` if not or an
``HttpResponse`` if you need something custom.
"""
from tastypie.compat import User

try:
username, api_key = self.extract_credentials(request)
Expand All @@ -207,6 +203,9 @@ def is_authenticated(self, request, **kwargs):
if not username or not api_key:
return self._unauthorized()

username_field = get_username_field()
User = get_user_model()

try:
lookup_kwargs = {username_field: username}
user = User.objects.get(**lookup_kwargs)
Expand Down Expand Up @@ -297,7 +296,8 @@ def get_identifier(self, request):
This implementation returns the user's username.
"""
return getattr(request.user, username_field)

return getattr(request.user, get_username_field())


class DigestAuthentication(Authentication):
Expand Down Expand Up @@ -383,6 +383,9 @@ def is_authenticated(self, request, **kwargs):
return True

def get_user(self, username):
username_field = get_username_field()
User = get_user_model()

try:
lookup_kwargs = {username_field: username}
user = User.objects.get(**lookup_kwargs)
Expand Down
28 changes: 14 additions & 14 deletions tastypie/compat.py
@@ -1,28 +1,28 @@
from __future__ import unicode_literals
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
import django

__all__ = ['User', 'AUTH_USER_MODEL']
__all__ = ['get_user_model', 'get_username_field', 'AUTH_USER_MODEL']

AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')

# Django 1.5+ compatibility
if django.VERSION >= (1, 5):
try:
from django.contrib.auth import get_user_model
User = get_user_model()
username_field = User.USERNAME_FIELD
except ImproperlyConfigured:
# The the users model might not be read yet.
# This can happen is when setting up the create_api_key signal, in your
# custom user module.
User = None
username_field = None
def get_user_model():
from django.contrib.auth import get_user_model as django_get_user_model

return django_get_user_model()

def get_username_field():
return get_user_model().USERNAME_FIELD
else:
from django.contrib.auth.models import User
username_field = 'username'
def get_user_model():
from django.contrib.auth.models import User

return User

def get_username_field():
return 'username'

def get_module_name(meta):
return getattr(meta, 'model_name', None) or getattr(meta, 'module_name')
Expand Down
12 changes: 9 additions & 3 deletions tastypie/fields.py
Expand Up @@ -713,6 +713,7 @@ def __init__(self, to, attribute, related_name=None, default=NOT_PROVIDED,

def dehydrate(self, bundle, for_list=True):
foreign_obj = None
error_to_raise = None

if isinstance(self.attribute, six.string_types):
attrs = self.attribute.split('__')
Expand All @@ -724,13 +725,18 @@ def dehydrate(self, bundle, for_list=True):
foreign_obj = getattr(foreign_obj, attr, None)
except ObjectDoesNotExist:
foreign_obj = None

elif callable(self.attribute):
previous_obj = bundle.obj
foreign_obj = self.attribute(bundle)

if not foreign_obj:
if not self.null:
raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr))

if callable(self.attribute):
raise ApiFieldError("The related resource for resource %s could not be found." % (previous_obj))
else:
raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr))

return None

self.fk_resource = self.get_related_resource(foreign_obj)
Expand Down
3 changes: 2 additions & 1 deletion tastypie/management/commands/backfill_api_keys.py
@@ -1,7 +1,7 @@
from __future__ import print_function
from __future__ import unicode_literals
from django.core.management.base import NoArgsCommand
from tastypie.compat import User
from tastypie.compat import get_user_model
from tastypie.models import ApiKey


Expand All @@ -12,6 +12,7 @@ def handle_noargs(self, **options):
"""Goes through all users and adds API keys for any that don't have one."""
self.verbosity = int(options.get('verbosity', 1))

User = get_user_model()
for user in User.objects.all().iterator():
try:
api_key = ApiKey.objects.get(user=user)
Expand Down

0 comments on commit 8fb26f4

Please sign in to comment.