Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Python3 compatibility; update Django to 1.11 #285

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.DS_Store
.venv*
.idea/**
*.pyc
dist
build
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[![Build Status](https://travis-ci.org/eudicots/Cactus.svg?branch=master)](https://travis-ci.org/eudicots/Cactus)

News
--------------

### Cactus 3 is out!

Expand Down
3 changes: 2 additions & 1 deletion cactus/deployment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def get_deployment_engine_class(provider):
_mod = __import__(module, fromlist=[engine])
except ImportError as e:
logger.error("Unable to import requested engine (%s) for provider %s", engine, provider)
logger.error("A required library was missing: %s", e.message)
logger.error("A required library was missing: %s", str(e))
logger.error("Please install the library and try again")
raise e
else:
return getattr(_mod, engine)
3 changes: 3 additions & 0 deletions cactus/i18n/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"pythonpath": None,
"traceback": True,
"all": False,
"no_color": False,
"exclude": [],
"fuzzy": False,
}

DEFAULT_MAKEMESSAGES_KWARGS = {
Expand Down
37 changes: 28 additions & 9 deletions cactus/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import traceback
import socket

import django.conf
from django import conf as django_conf

from cactus import ui as ui_module
from cactus.config.router import ConfigRouter
Expand Down Expand Up @@ -142,10 +142,30 @@ def setup(self):
Configure django to use both our template and pages folder as locations
to look for included templates.
"""

settings = {
"TEMPLATE_DIRS": [self.template_path, self.page_path],
"INSTALLED_APPS": ['django_markwhat'],
"TEMPLATES": [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [self.template_path, self.page_path],
'APP_DIRS': False,
'OPTIONS': {
'context_processors': [
# list of default context processors in Django 1.6
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.debug",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
"django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages"
],
'builtins': [
'cactus.template_tags'
],
}
}
]
}

if self.locale is not None:
Expand All @@ -156,13 +176,12 @@ def setup(self):
"LOCALE_PATHS": [self.locale_path],
})

django.conf.settings.configure(**settings)
django_conf.settings.configure(**settings)

import django
django.setup()


# - Importing here instead of the top-level makes it work on Python 3.x (!)
# - loading add_to_builtins from loader implictly loads the loader_tags built-in
# - Injecting our tags using add_to_builtins ensures that Cactus tags don't require an import
from django.template.loader import add_to_builtins
add_to_builtins('cactus.template_tags')

def verify_path(self):
"""
Expand Down
5 changes: 2 additions & 3 deletions cactus/template_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
import os
import logging

from django.template.base import Library
from django.conf import settings
from django import template
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe

logger = logging.getLogger(__name__)

register = Library()
register = template.Library()


def static(context, link_url):
Expand Down
89 changes: 89 additions & 0 deletions cactus/utils/inspect23.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
Python2/3 compatible version of inspect.
Source: https://github.com/timgraham/django/blob/3872a33132a4bb6aa22b237927597bbfdf6f21d7/django/utils/inspect.py

Slightly modified so getargspec() always returns a named tuple (ArgSpec).
"""

from __future__ import absolute_import

import inspect
import six
from collections import namedtuple

ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')


def getargspec(func):
if six.PY2:
return inspect.getargspec(func)

sig = inspect.signature(func)
args = [
p.name for p in sig.parameters.values()
if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
]
varargs = [
p.name for p in sig.parameters.values()
if p.kind == inspect.Parameter.VAR_POSITIONAL
]
varargs = varargs[0] if varargs else None
varkw = [
p.name for p in sig.parameters.values()
if p.kind == inspect.Parameter.VAR_KEYWORD
]
varkw = varkw[0] if varkw else None
defaults = [
p.default for p in sig.parameters.values()
if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD and p.default is not p.empty
] or None
return ArgSpec(args, varargs, varkw, defaults)


def get_func_args(func):
if six.PY2:
argspec = inspect.getargspec(func)
return argspec.args[1:] # ignore 'self'

sig = inspect.signature(func)
return [
arg_name for arg_name, param in sig.parameters.items()
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
]


def func_accepts_kwargs(func):
if six.PY2:
# Not all callables are inspectable with getargspec, so we'll
# try a couple different ways but in the end fall back on assuming
# it is -- we don't want to prevent registration of valid but weird
# callables.
try:
argspec = inspect.getargspec(func)
except TypeError:
try:
argspec = inspect.getargspec(func.__call__)
except (TypeError, AttributeError):
argspec = None
return not argspec or argspec[2] is not None

return any(
p for p in inspect.signature(func).parameters.values()
if p.kind == p.VAR_KEYWORD
)


def func_has_no_args(func):
args = inspect.getargspec(func)[0] if six.PY2 else [
p for p in inspect.signature(func).parameters.values()
if p.kind == p.POSITIONAL_OR_KEYWORD and p.default is p.empty
]
return len(args) == 1


def func_supports_parameter(func, parameter):
if six.PY3:
return parameter in inspect.signature(func).parameters
else:
args, varargs, varkw, defaults = inspect.getargspec(func)
return parameter in args
7 changes: 4 additions & 3 deletions cactus/utils/internal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#coding:utf-8
import six
import inspect
from .inspect23 import getargspec as six_getargspec

# Adapted from: http://kbyanc.blogspot.com/2007/07/python-more-generic-getargspec.html

Expand Down Expand Up @@ -33,16 +34,16 @@ def getargspec(obj):
raise TypeError("%s is not callable" % type(obj))
try:
if inspect.isfunction(obj):
return inspect.getargspec(obj)
return six_getargspec(obj)
elif hasattr(obj, FUNC_OBJ_ATTR):
# For methods or classmethods drop the first
# argument from the returned list because
# python supplies that automatically for us.
# Note that this differs from what
# inspect.getargspec() returns for methods.
# six_getargspec()() returns for methods.
# NB: We use im_func so we work with
# instancemethod objects also.
spec = inspect.getargspec(getattr(obj, FUNC_OBJ_ATTR))
spec = six_getargspec(getattr(obj, FUNC_OBJ_ATTR))
return inspect.ArgSpec(spec.args[:1], spec.varargs, spec.keywords, spec.defaults)
elif inspect.isclass(obj):
return getargspec(obj.__init__)
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Django>=1.6,<1.7
Django==1.11.29
django-markwhat>=1.4,<2
markdown2
argparse
Expand Down
6 changes: 3 additions & 3 deletions run.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env python
# encoding: utf-8

import sys
import cactus

from cactus.cli import main

print "Using: %s" % cactus.__file__
print("Using: %s" % cactus.__file__)

if __name__ == "__main__":
main()
main(sys.argv[1:])