From 3933ce982d16e6c9b563bf9150eda4f23d30d606 Mon Sep 17 00:00:00 2001 From: "thi.guten" Date: Tue, 12 Sep 2017 08:26:00 +0200 Subject: [PATCH 1/4] Update README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46860bbc..38de98d7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ -[![Build Status](https://travis-ci.org/eudicots/Cactus.svg?branch=master)](https://travis-ci.org/eudicots/Cactus) +Fork Info +--------- + +This is a fork of Cactus 3. It extends the `{% url %}` template tag with language/i18n support by adding the language code to the root URL. This is by no means bullet proof - it may break certain website builds. It works for me, though. + +When I have time to straighten this up and document it properly, I'll send a pull request to the Cactus team - promise! + + -News --------------- ### Cactus 3 is out! From c5a68d1bcd93cd5afd2424e229d68385b1dd9fd4 Mon Sep 17 00:00:00 2001 From: Markus Thielen Date: Wed, 27 Apr 2022 11:06:12 +0200 Subject: [PATCH 2/4] fixed #280; updated Django to 1.11; removed Python3 deprecation warnings --- .gitignore | 2 + README.md | 9 ---- cactus/i18n/commands.py | 3 ++ cactus/site.py | 37 ++++++++++++---- cactus/template_tags.py | 5 +-- cactus/utils/inspect23.py | 89 +++++++++++++++++++++++++++++++++++++++ cactus/utils/internal.py | 7 +-- requirements.txt | 2 +- run.py | 6 +-- 9 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 cactus/utils/inspect23.py diff --git a/.gitignore b/.gitignore index 0efe71c2..02a202cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .DS_Store +.venv/** +.idea/** *.pyc dist build diff --git a/README.md b/README.md index 38de98d7..31374934 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,3 @@ -Fork Info ---------- - -This is a fork of Cactus 3. It extends the `{% url %}` template tag with language/i18n support by adding the language code to the root URL. This is by no means bullet proof - it may break certain website builds. It works for me, though. - -When I have time to straighten this up and document it properly, I'll send a pull request to the Cactus team - promise! - - - ### Cactus 3 is out! diff --git a/cactus/i18n/commands.py b/cactus/i18n/commands.py index 0a67db18..c680ac73 100644 --- a/cactus/i18n/commands.py +++ b/cactus/i18n/commands.py @@ -12,6 +12,9 @@ "pythonpath": None, "traceback": True, "all": False, + "no_color": False, + "exclude": [], + "fuzzy": False, } DEFAULT_MAKEMESSAGES_KWARGS = { diff --git a/cactus/site.py b/cactus/site.py index beacc92f..51ba3351 100644 --- a/cactus/site.py +++ b/cactus/site.py @@ -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 @@ -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: @@ -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): """ diff --git a/cactus/template_tags.py b/cactus/template_tags.py index f5b46d51..bba06cd5 100644 --- a/cactus/template_tags.py +++ b/cactus/template_tags.py @@ -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): diff --git a/cactus/utils/inspect23.py b/cactus/utils/inspect23.py new file mode 100644 index 00000000..e9e43f69 --- /dev/null +++ b/cactus/utils/inspect23.py @@ -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 \ No newline at end of file diff --git a/cactus/utils/internal.py b/cactus/utils/internal.py index 9b507af5..d2f996b8 100644 --- a/cactus/utils/internal.py +++ b/cactus/utils/internal.py @@ -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 @@ -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__) diff --git a/requirements.txt b/requirements.txt index 3116e4b7..37fae6f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django>=1.6,<1.7 +Django==1.11.29 django-markwhat>=1.4,<2 markdown2 argparse diff --git a/run.py b/run.py index de31e5bf..653634b0 100755 --- a/run.py +++ b/run.py @@ -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() \ No newline at end of file + main(sys.argv[1:]) From 51de7b7526a60585baa5a2cb335e60a0c4311847 Mon Sep 17 00:00:00 2001 From: Markus Thielen Date: Wed, 27 Apr 2022 12:47:57 +0200 Subject: [PATCH 3/4] gitignore all .venv* --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 02a202cc..4e429af1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -.venv/** +.venv* .idea/** *.pyc dist From 6b3697823c00ac56c96fda7369744fcf4bf3780f Mon Sep 17 00:00:00 2001 From: Markus Thielen Date: Fri, 24 Jun 2022 17:59:36 +0200 Subject: [PATCH 4/4] python 3.10 compatibility fix --- cactus/deployment/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cactus/deployment/__init__.py b/cactus/deployment/__init__.py index ea41799b..500272d7 100644 --- a/cactus/deployment/__init__.py +++ b/cactus/deployment/__init__.py @@ -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)