1. tkadm30
  2. django-hotsauce

Commits

Comments (0)

Files changed (29)

File Makefile Modified

View file
  • Ignore whitespace
  • Hide word diff
 # Enable experimental I18N support
 WITH_I18N?="YES"
 
+# Enable experimental ORM support
+WITH_MODEL?="YES"
+
+# Enable experimental session management
+WITH_SESSION?="YES"
+
 
 #No support yet for Python3000 aka GoogleSwallow
 ifdef WITH_CYTHON
-    CYTHON_MODULES:=\
-	lib/notmm/controllers/wsgi.pyx \
-	lib/notmm/controllers/session.pyx 
+    CYTHON_MODULES:=lib/notmm/controllers/wsgi.pyx 
+ifdef WITH_SESSION
+	CYTHON_MODULES+=lib/notmm/controllers/session.pyx 
+endif
+ifdef WITH_MODEL    
+    CYTHON_MODULES+=lib/notmm/dbapi/orm/model.pyx
+endif
 ifdef WITH_SCHEVO        
     CYTHON_MODULES+=lib/notmm/controllers/schevo.pyx 
 endif

File README Modified

View file
  • Ignore whitespace
  • Hide word diff
  
- Django-hotsauce 0.6.4
+ Django-hotsauce 0.6.6
  =====================
 
- Welcome to the notmm toolkit, a open web application 
+ Welcome to the django-hotsauce toolkit, a open web application 
  platform written in Python.  
  
- The notmm (django-hotsauce) toolkit aims to provide tools for rapid web application
+ The django-hotsauce toolkit aims to provide tools for rapid web application
  development and testing on top of the Django framework and WSGI.
 
  Getting Started

File admin/PKG-INFO.in Modified

View file
  • Ignore whitespace
  • Hide word diff
 Metadata-Version: 1.0
 Name: django-hotsauce
-Version: 0.6.5
+Version: 0.6.6
 Summary: Scalable and heterogeneous web toolkit sitting on top of Django and others
 Homepage: http://isotopesoftware.ca/
 Author: Etienne Robillard

File bootstrap Modified

View file
  • Ignore whitespace
  • Hide word diff
 }
 
 install_package "pyyaml"
-install_package "Cython>=0.18"
+install_package "Cython>=0.24.1"
 
 
 echo "Now run 'sudo make develop PYTHON=$python_exec' if you intend developing in place."

File extras/libauthkit/authkit/authorize/decorators.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 
 __all__ = ['authorize', 'authorized']
 
-def authorize(perm, errorHandler):
+def authorize(perm, errorHandler=NotAuthorizedError):
     def decorator(view_func):
         @wraps(view_func)
         def _wrapper(*args, **kwargs):
                 raise errorHandler('You must authenticate first.')
                 # use ``func`` as the start_response callback
             else:
-                #def on_authorize(environ, start_response):
-                #    return perm.check(request, environ, start_response)
-                #is_authorized = bool(on_authorize(request.environ.copy(), view_func))
-                #if is_authorized:
-                #    return view_func(request, *args, **kwargs)
-                #else:
-                #    return errorHandler("You're not authorized to see this page!")
-                return view_func(request, **kwargs)
+                def on_authorize(environ, start_response):
+                    return perm.check(request, environ, start_response)
+                is_authorized = bool(on_authorize(request.environ.copy(), view_func))
+                if is_authorized:
+                    return view_func(request, *args, **kwargs)
+                else:
+                    return errorHandler("You're not authorized to see this page!")
+                #return view_func(request, **kwargs)
         #return wraps(view_func)(_wrapper, **kwargs)
         return _wrapper
     return decorator

File extras/libauthkit/authkit/authorize/exc.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 __all__ = ['PermissionError', 'NotAuthenticatedError', 
     'NotAuthorizedError', 'NonConformingPermissionError']
 
+from notmm.utils.wsgilib import HTTPUnauthorized
 
 class PermissionError(BaseException):
     """
     code = 401
     title = 'Not Authenticated'
 
-class NotAuthorizedError(NotAuthenticatedError):
+class NotAuthorizedError(NotAuthenticatedError, HTTPUnauthorized):
     """
     Raised when a permission check fails because the user is not authorized.
 

File extras/libschevo/lib/schevo/management/__init__.py Added

  • Ignore whitespace
  • Hide word diff
Empty file added.

File extras/libschevo/lib/schevo/management/commands/__init__.py Added

  • Ignore whitespace
  • Hide word diff
Empty file added.

File extras/libschevo/lib/schevo/management/commands/debug.py Added

View file
  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python
+print("Hello world")

File lib/notmm/dbapi/orm/__init__.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 
 #XXX: AnonymousUser should be defined in blogengine.contrib.anonymoususer
 #from models import AnonymousUser
-from .model import Model, ModelManager
+#from .model import ModelManager
 
 from .schevo_compat import XdserverProxy
 from .zodb_compat import ClientStorageProxy, ZODBFileStorageProxy

File lib/notmm/dbapi/orm/management/__init__.py Added

View file
  • Ignore whitespace
  • Hide word diff
+from __future__ import unicode_literals
+
+import os
+import pkgutil
+import sys
+from collections import OrderedDict, defaultdict
+from importlib import import_module
+
+import django
+from django.apps import apps
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.core.management.base import (
+    BaseCommand, CommandError, CommandParser, handle_default_options,
+)
+from django.core.management.color import color_style
+from django.utils import autoreload, lru_cache, six
+from django.utils._os import npath, upath
+from django.utils.encoding import force_text
+
+try:
+    import schevo
+except ImportError:
+    # Schevo is not installed
+    pass
+
+def find_commands(management_dir):
+    """
+    Given a path to a management directory, returns a list of all the command
+    names that are available.
+
+    Returns an empty list if no commands are defined.
+    """
+    command_dir = os.path.join(management_dir, 'commands')
+    return [name for _, name, is_pkg in pkgutil.iter_modules([npath(command_dir)])
+            if not is_pkg and not name.startswith('_')]
+
+
+def load_command_class(app_name, name):
+    """
+    Given a command name and an application name, returns the Command
+    class instance. All errors raised by the import process
+    (ImportError, AttributeError) are allowed to propagate.
+    """
+    module = import_module('%s.management.commands.%s' % (app_name, name))
+    return module.Command()
+
+
+@lru_cache.lru_cache(maxsize=None)
+def get_commands():
+    """
+    Returns a dictionary mapping command names to their callback applications.
+
+    This works by looking for a management.commands package in django.core, and
+    in each installed application -- if a commands package exists, all commands
+    in that package are registered.
+
+    Core commands are always included. If a settings module has been
+    specified, user-defined commands will also be included.
+
+    The dictionary is in the format {command_name: app_name}. Key-value
+    pairs from this dictionary can then be used in calls to
+    load_command_class(app_name, command_name)
+
+    If a specific version of a command must be loaded (e.g., with the
+    startapp command), the instantiated module can be placed in the
+    dictionary in place of the application name.
+
+    The dictionary is cached on the first call and reused on subsequent
+    calls.
+    """
+    commands = {name: 'notmm.dbapi.orm' for name in find_commands(upath(__path__[0]))}
+
+    if not settings.configured:
+        return commands
+    
+    configs = apps.get_app_configs()
+
+    for app_config in reversed(list(apps.get_app_configs())):
+        path = os.path.join(app_config.path, 'management')
+        commands.update({name: app_config.name for name in find_commands(path)})
+
+    return commands
+
+
+def call_command(command_name, *args, **options):
+    """
+    Calls the given command, with the given options and args/kwargs.
+
+    This is the primary API you should use for calling specific commands.
+
+    `name` may be a string or a command object. Using a string is preferred
+    unless the command object is required for further processing or testing.
+
+    Some examples:
+        call_command('migrate')
+        call_command('shell', plain=True)
+        call_command('sqlmigrate', 'myapp')
+
+        from django.core.management.commands import flush
+        cmd = flush.Command()
+        call_command(cmd, verbosity=0, interactive=False)
+        # Do something with cmd ...
+    """
+    if isinstance(command_name, BaseCommand):
+        # Command object passed in.
+        command = command_name
+        command_name = command.__class__.__module__.split('.')[-1]
+    else:
+        # Load the command object by name.
+        try:
+            app_name = get_commands()[command_name]
+        except KeyError:
+            raise CommandError("Unknown command: %r" % command_name)
+
+        if isinstance(app_name, BaseCommand):
+            # If the command is already loaded, use it directly.
+            command = app_name
+        else:
+            command = load_command_class(app_name, command_name)
+
+    # Simulate argument parsing to get the option defaults (see #10080 for details).
+    parser = command.create_parser('', command_name)
+    # Use the `dest` option name from the parser option
+    opt_mapping = {
+        sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest
+        for s_opt in parser._actions if s_opt.option_strings
+    }
+    arg_options = {opt_mapping.get(key, key): value for key, value in options.items()}
+    defaults = parser.parse_args(args=[force_text(a) for a in args])
+    defaults = dict(defaults._get_kwargs(), **arg_options)
+    # Move positional args out of options to mimic legacy optparse
+    args = defaults.pop('args', ())
+    if 'skip_checks' not in options:
+        defaults['skip_checks'] = True
+
+    return command.execute(*args, **defaults)
+
+
+class ManagementUtility(object):
+    """
+    Encapsulates the logic of the django-admin and manage.py utilities.
+
+    A ManagementUtility has a number of commands, which can be manipulated
+    by editing the self.commands dictionary.
+    """
+    def __init__(self, argv=None):
+        self.argv = argv or sys.argv[:]
+        self.prog_name = os.path.basename(self.argv[0])
+        self.settings_exception = None
+
+    def main_help_text(self, commands_only=False):
+        """
+        Returns the script's main help text, as a string.
+        """
+        if commands_only:
+            usage = sorted(get_commands().keys())
+        else:
+            usage = [
+                "",
+                "Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name,
+                "",
+                "Available subcommands:",
+            ]
+            commands_dict = defaultdict(lambda: [])
+            for name, app in six.iteritems(get_commands()):
+                if app == 'notmm.dbapi.orm':
+                    app = 'notmm'
+                else:
+                    app = app.rpartition('.')[-1]
+                commands_dict[app].append(name)
+            style = color_style()
+            for app in sorted(commands_dict.keys()):
+                usage.append("")
+                usage.append(style.NOTICE("[%s]" % app))
+                for name in sorted(commands_dict[app]):
+                    usage.append("    %s" % name)
+            # Output an extra note if settings are not properly configured
+            if self.settings_exception is not None:
+                usage.append(style.NOTICE(
+                    "Note that only Django core commands are listed "
+                    "as settings are not properly configured (error: %s)."
+                    % self.settings_exception))
+
+        return '\n'.join(usage)
+
+    def fetch_command(self, subcommand):
+        """
+        Tries to fetch the given subcommand, printing a message with the
+        appropriate command called from the command line (usually
+        "django-admin" or "manage.py") if it can't be found.
+        """
+        # Get commands outside of try block to prevent swallowing exceptions
+        commands = get_commands()
+        try:
+            app_name = commands[subcommand]
+        except KeyError:
+            if os.environ.get('DJANGO_SETTINGS_MODULE'):
+                # If `subcommand` is missing due to misconfigured settings, the
+                # following line will retrigger an ImproperlyConfigured exception
+                # (get_commands() swallows the original one) so the user is
+                # informed about it.
+                settings.INSTALLED_APPS
+            else:
+                sys.stderr.write("No Django settings specified.\n")
+            sys.stderr.write(
+                "Unknown command: %r\nType '%s help' for usage.\n"
+                % (subcommand, self.prog_name)
+            )
+            sys.exit(1)
+        if isinstance(app_name, BaseCommand):
+            # If the command is already loaded, use it directly.
+            klass = app_name
+        else:
+            klass = load_command_class(app_name, subcommand)
+        return klass
+
+    def autocomplete(self):
+        """
+        Output completion suggestions for BASH.
+
+        The output of this function is passed to BASH's `COMREPLY` variable and
+        treated as completion suggestions. `COMREPLY` expects a space
+        separated string as the result.
+
+        The `COMP_WORDS` and `COMP_CWORD` BASH environment variables are used
+        to get information about the cli input. Please refer to the BASH
+        man-page for more information about this variables.
+
+        Subcommand options are saved as pairs. A pair consists of
+        the long option string (e.g. '--exclude') and a boolean
+        value indicating if the option requires arguments. When printing to
+        stdout, an equal sign is appended to options which require arguments.
+
+        Note: If debugging this function, it is recommended to write the debug
+        output in a separate file. Otherwise the debug output will be treated
+        and formatted as potential completion suggestions.
+        """
+        # Don't complete if user hasn't sourced bash_completion file.
+        if 'DJANGO_AUTO_COMPLETE' not in os.environ:
+            return
+
+        cwords = os.environ['COMP_WORDS'].split()[1:]
+        cword = int(os.environ['COMP_CWORD'])
+
+        try:
+            curr = cwords[cword - 1]
+        except IndexError:
+            curr = ''
+
+        subcommands = list(get_commands()) + ['help']
+        options = [('--help', False)]
+
+        # subcommand
+        if cword == 1:
+            print(' '.join(sorted(filter(lambda x: x.startswith(curr), subcommands))))
+        # subcommand options
+        # special case: the 'help' subcommand has no options
+        elif cwords[0] in subcommands and cwords[0] != 'help':
+            subcommand_cls = self.fetch_command(cwords[0])
+            # special case: add the names of installed apps to options
+            if cwords[0] in ('dumpdata', 'sqlmigrate', 'sqlsequencereset', 'test'):
+                try:
+                    app_configs = apps.get_app_configs()
+                    # Get the last part of the dotted path as the app name.
+                    options.extend((app_config.label, 0) for app_config in app_configs)
+                except ImportError:
+                    # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The
+                    # user will find out once they execute the command.
+                    pass
+            parser = subcommand_cls.create_parser('', cwords[0])
+            options.extend(
+                (sorted(s_opt.option_strings)[0], s_opt.nargs != 0)
+                for s_opt in parser._actions if s_opt.option_strings
+            )
+            # filter out previously specified options from available options
+            prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
+            options = [opt for opt in options if opt[0] not in prev_opts]
+
+            # filter options by current input
+            options = sorted((k, v) for k, v in options if k.startswith(curr))
+            for option in options:
+                opt_label = option[0]
+                # append '=' to options which require args
+                if option[1]:
+                    opt_label += '='
+                print(opt_label)
+        # Exit code of the bash completion function is never passed back to
+        # the user, so it's safe to always exit with 0.
+        # For more details see #25420.
+        sys.exit(0)
+
+    def execute(self):
+        """
+        Given the command-line arguments, this figures out which subcommand is
+        being run, creates a parser appropriate to that command, and runs it.
+        """
+        try:
+            subcommand = self.argv[1]
+        except IndexError:
+            subcommand = 'help'  # Display help if no arguments were given.
+
+        # Preprocess options to extract --settings and --pythonpath.
+        # These options could affect the commands that are available, so they
+        # must be processed early.
+        parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)
+        parser.add_argument('--settings')
+        parser.add_argument('--pythonpath')
+        parser.add_argument('args', nargs='*')  # catch-all
+        try:
+            options, args = parser.parse_known_args(self.argv[2:])
+            handle_default_options(options)
+        except CommandError:
+            pass  # Ignore any option errors at this point.
+
+        no_settings_commands = [
+            'help', 'version', '--help', '--version', '-h',
+            'compilemessages', 'makemessages',
+            'startapp', 'startproject',
+        ]
+
+        try:
+            settings.INSTALLED_APPS
+        except ImproperlyConfigured as exc:
+            self.settings_exception = exc
+            # A handful of built-in management commands work without settings.
+            # Load the default settings -- where INSTALLED_APPS is empty.
+            if subcommand in no_settings_commands:
+                settings.configure()
+
+        if settings.configured:
+            # Start the auto-reloading dev server even if the code is broken.
+            # The hardcoded condition is a code smell but we can't rely on a
+            # flag on the command class because we haven't located it yet.
+            if subcommand == 'runserver' and '--noreload' not in self.argv:
+                try:
+                    autoreload.check_errors(django.setup)()
+                except Exception:
+                    # The exception will be raised later in the child process
+                    # started by the autoreloader. Pretend it didn't happen by
+                    # loading an empty list of applications.
+                    apps.all_models = defaultdict(OrderedDict)
+                    apps.app_configs = OrderedDict()
+                    apps.apps_ready = apps.models_ready = apps.ready = True
+
+            # In all other cases, django.setup() is required to succeed.
+            else:
+                django.setup()
+
+        self.autocomplete()
+
+        if subcommand == 'help':
+            if '--commands' in args:
+                sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
+            elif len(options.args) < 1:
+                sys.stdout.write(self.main_help_text() + '\n')
+            else:
+                self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])
+        # Special-cases: We want 'django-admin --version' and
+        # 'django-admin --help' to work, for backwards compatibility.
+        elif subcommand == 'version' or self.argv[1:] == ['--version']:
+            sys.stdout.write(django.get_version() + '\n')
+        elif self.argv[1:] in (['--help'], ['-h']):
+            sys.stdout.write(self.main_help_text() + '\n')
+        else:
+            self.fetch_command(subcommand).run_from_argv(self.argv)
+
+
+def execute_from_command_line(argv=None):
+    """
+    A simple method that runs a ManagementUtility.
+    """
+    utility = ManagementUtility(argv)
+    utility.execute()

File lib/notmm/dbapi/orm/management/commands/__init__.py Added

  • Ignore whitespace
  • Hide word diff
Empty file added.

File lib/notmm/dbapi/orm/management/commands/introspect.py Added

View file
  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python
+"""
+Model introspection API for django-hotsauce
+"""
+from importlib import import_module
+
+__all__ = ['by_module_name']
+
+moduleList = ('configuration', 'handlers', 'signals', 'views', 'urls', 'model')
+
+def by_module_name(modname):
+    features = {}
+    mod = import_module(modname)
+    features['module'] = mod
+    for item in moduleList:
+        if hasattr(mod, item):
+            features[item] = getattr(mod, item)
+    return features

File lib/notmm/dbapi/orm/management/commands/runserver.py Added

View file
  • Ignore whitespace
  • Hide word diff
+from __future__ import unicode_literals
+
+import errno
+import os
+import re
+import socket
+import sys
+from datetime import datetime
+
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.core.servers.basehttp import get_internal_wsgi_application, run
+from django.utils import autoreload, six
+from django.utils.encoding import force_text, get_system_encoding
+
+
+naiveip_re = re.compile(r"""^(?:
+(?P<addr>
+    (?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) |         # IPv4 address
+    (?P<ipv6>\[[a-fA-F0-9:]+\]) |               # IPv6 address
+    (?P<fqdn>[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN
+):)?(?P<port>\d+)$""", re.X)
+
+
+class Command(BaseCommand):
+    help = "Starts a lightweight Web server for development."
+
+    # Validation is called explicitly each time the server is reloaded.
+    requires_system_checks = False
+    leave_locale_alone = True
+
+    default_port = '8000'
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            'addrport', nargs='?',
+            help='Optional port number, or ipaddr:port'
+        )
+        parser.add_argument(
+            '--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
+            help='Tells Django to use an IPv6 address.',
+        )
+        parser.add_argument(
+            '--nothreading', action='store_false', dest='use_threading', default=True,
+            help='Tells Django to NOT use threading.',
+        )
+        parser.add_argument(
+            '--noreload', action='store_false', dest='use_reloader', default=True,
+            help='Tells Django to NOT use the auto-reloader.',
+        )
+
+    def execute(self, *args, **options):
+        if options['no_color']:
+            # We rely on the environment because it's currently the only
+            # way to reach WSGIRequestHandler. This seems an acceptable
+            # compromise considering `runserver` runs indefinitely.
+            os.environ[str("DJANGO_COLORS")] = str("nocolor")
+        super(Command, self).execute(*args, **options)
+
+    def get_handler(self, *args, **options):
+        """
+        Returns the default WSGI handler for the runner.
+        """
+        return get_internal_wsgi_application()
+
+    def handle(self, *args, **options):
+        from django.conf import settings
+
+        if not settings.DEBUG and not settings.ALLOWED_HOSTS:
+            raise CommandError('You must set settings.ALLOWED_HOSTS if DEBUG is False.')
+
+        self.use_ipv6 = options['use_ipv6']
+        if self.use_ipv6 and not socket.has_ipv6:
+            raise CommandError('Your Python does not support IPv6.')
+        self._raw_ipv6 = False
+        if not options['addrport']:
+            self.addr = ''
+            self.port = self.default_port
+        else:
+            m = re.match(naiveip_re, options['addrport'])
+            if m is None:
+                raise CommandError('"%s" is not a valid port number '
+                                   'or address:port pair.' % options['addrport'])
+            self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups()
+            if not self.port.isdigit():
+                raise CommandError("%r is not a valid port number." % self.port)
+            if self.addr:
+                if _ipv6:
+                    self.addr = self.addr[1:-1]
+                    self.use_ipv6 = True
+                    self._raw_ipv6 = True
+                elif self.use_ipv6 and not _fqdn:
+                    raise CommandError('"%s" is not a valid IPv6 address.' % self.addr)
+        if not self.addr:
+            self.addr = '::1' if self.use_ipv6 else '127.0.0.1'
+            self._raw_ipv6 = self.use_ipv6
+        self.run(**options)
+
+    def run(self, **options):
+        """
+        Runs the server, using the autoreloader if needed
+        """
+        use_reloader = options['use_reloader']
+
+        if use_reloader:
+            autoreload.main(self.inner_run, None, options)
+        else:
+            self.inner_run(None, **options)
+
+    def inner_run(self, *args, **options):
+        # If an exception was silenced in ManagementUtility.execute in order
+        # to be raised in the child process, raise it now.
+        autoreload.raise_last_exception()
+
+        threading = options['use_threading']
+        # 'shutdown_message' is a stealth option.
+        shutdown_message = options.get('shutdown_message', '')
+        quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C'
+
+        self.stdout.write("Performing system checks...\n\n")
+        self.check(display_num_errors=True)
+        # Need to check migrations here, so can't use the
+        # requires_migrations_check attribute.
+        self.check_migrations()
+        now = datetime.now().strftime('%B %d, %Y - %X')
+        if six.PY2:
+            now = now.decode(get_system_encoding())
+        self.stdout.write(now)
+        self.stdout.write((
+            "Django version %(version)s, using settings %(settings)r\n"
+            "Starting development server at http://%(addr)s:%(port)s/\n"
+            "Quit the server with %(quit_command)s.\n"
+        ) % {
+            "version": self.get_version(),
+            "settings": settings.SETTINGS_MODULE,
+            "addr": '[%s]' % self.addr if self._raw_ipv6 else self.addr,
+            "port": self.port,
+            "quit_command": quit_command,
+        })
+
+        try:
+            handler = self.get_handler(*args, **options)
+            run(self.addr, int(self.port), handler,
+                ipv6=self.use_ipv6, threading=threading)
+        except socket.error as e:
+            # Use helpful error messages instead of ugly tracebacks.
+            ERRORS = {
+                errno.EACCES: "You don't have permission to access that port.",
+                errno.EADDRINUSE: "That port is already in use.",
+                errno.EADDRNOTAVAIL: "That IP address can't be assigned to.",
+            }
+            try:
+                error_text = ERRORS[e.errno]
+            except KeyError:
+                error_text = force_text(e)
+            self.stderr.write("Error: %s" % error_text)
+            # Need to use an OS exit because sys.exit doesn't work in a thread
+            os._exit(1)
+        except KeyboardInterrupt:
+            if shutdown_message:
+                self.stdout.write(shutdown_message)
+            sys.exit(0)
+
+# Kept for backward compatibility
+BaseRunserverCommand = Command

File lib/notmm/dbapi/orm/management/commands/version.py Added

  • Ignore whitespace
  • Hide word diff
Empty file added.

File lib/notmm/dbapi/orm/model.pxd Added

View file
  • Ignore whitespace
  • Hide word diff
+cdef class ModelBase(object):
+    pass
+

File lib/notmm/dbapi/orm/model.py Deleted

  • Ignore whitespace
  • Hide word diff
-#!/usr/bin/env python
-"""Base model classes for django-hotsauce"""
-from notmm.dbapi.orm import DatabaseProxy
-
-__all__ = ('Model', 'ModelManager')
-
-class Model(object):
-    db = None
-    backend = None
-    def __init__(self, addr=None):
-        self.addr = addr # zodb://127.0.0.1:4343
-    def __str__(self):
-        return str(self.addr)
-    def __getattr__(self, name):
-        return getattr(self.db, name)
-
-class ModelManager(Model):
-    def setup(self, addr, backend=DatabaseProxy):
-        self.backend = backend
-        self.db = backend(addr)
-        return self.db
-

File lib/notmm/dbapi/orm/model.pyx Added

View file
  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python
+"""Base model classes for django-hotsauce"""
+import logging
+import schevo.mt
+
+log = logging.getLogger(__name__)
+from notmm.dbapi.orm.model cimport ModelBase
+from notmm.dbapi.orm import DatabaseProxy, ClientStorageProxy
+from notmm.utils.django_settings import LazySettings
+
+from management.commands import introspect
+
+_settings = LazySettings()
+_installed_models = []
+
+__all__ = ('Database', 'DurusDatabase', 'ZODBDatabase', 'Model', 'ModelManager', 'populate', 'setup', 'get_models')
+
+def get_models():
+    return _installed_models
+
+def setup():
+    populate()
+
+def populate(verbose=False):
+    """Populate _installed_models with the list of configured models"""
+    for app in _settings.INSTALLED_APPS:
+        if verbose:
+            log.debug("Configuring %s" % app)
+        app_info = introspect.by_module_name(app)
+        _installed_models.append(app_info)
+
+class Model(ModelBase):
+
+    initialized = False
+    multithread = True
+    
+    class Meta:
+        db_backend = None
+        db_addr = None
+
+    def __new__(cls, *args, **kwargs):
+        if hasattr(cls, 'db'):
+            cls.initialized = cls.db.conn._is_open
+        else:
+            #log.debug("Configuring database at %s" % cls.Meta.db_addr)
+            cls.db = cls.Meta.db_backend(cls.Meta.db_addr)
+            cls.extent = cls.db.extent(cls.__name__)
+        if not cls.initialized:
+            #log.debug("Opening database connection...")
+            cls.db.backend.open()
+        if cls.multithread:
+            schevo.mt.install(cls.db)
+        assert cls.db.conn._is_open==True
+        return super(Model, cls).__new__(cls)
+    
+    def __init__(self, **kwargs):
+        self.kwargs = kwargs
+        
+    def __str__(self):
+        return str(self.Meta.db_addr)
+    
+    ### Public methods
+    def save(self, commit=True):
+        lock = self.db.write_lock()
+        with lock:
+            #if self.initialized:
+            tx = self.extent.t.create(**self.kwargs)
+            if commit:
+                self.db.execute(tx)
+                self.db._commit()
+        lock.release()
+        return self
+
+    #def __getattr__(self, name):
+    #    assert self.initialized==True
+    #    return getattr(self.db, name)

File lib/notmm/http/httpserver/__init__.py Modified

View file
  • Ignore whitespace
  • Hide word diff
     
 log = logging.getLogger(__name__)
 
-__all__ = ('WSGIServerBase',
-           'BannerBase',
-           'get_bind_addr', 
-           'daemonize', 
-           'make_server')
+__all__ = ('WSGIServerBase', 'BannerBase', 'get_bind_addr', 'daemonize')
 
 class BannerBase(object):
     """This is a simple startup banner.

File lib/notmm/release.py Modified

View file
  • Ignore whitespace
  • Hide word diff
-VERSION = '0.6.5'
+VERSION = '0.6.6'
 BASEVERSION = VERSION 

File lib/notmm/utils/wsgilib/request.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 #    from notmm.utils.wsgilib import MultiDict
 #except ImportError:
 #    from webob.multidict import MultiDict
-from multidict import MultiDict
+try:
+    from webob.multidict import MultiDict
+except ImportError:
+    from multidict import MultiDict
 
 
 __all__ = ['HTTPRequest']
         #    self.wsgi_environ.update(environ)
         #self._environ['REQUEST_METHOD'] = method
         # parse the query string
-        if 'QUERY_STRING' in environ:
-            self.query_args =  MultiDict(environ['QUERY_STRING'])
-        else:
-            self.query_args = None
+        #if 'QUERY_STRING' in environ:
+        #    import pdb; pdb.set_trace()
+        #    self.query_args =  MultiDict(environ['QUERY_STRING'])
+        #else:
+        #    self.query_args = MultiDict()
 
     def get_remote_user(self):
         '''Subclasses should override this method to retrieve a User storage class

File setup.py Modified

View file
  • Ignore whitespace
  • Hide word diff
     Extension('notmm.controllers.elixir', \
         ['lib/notmm/controllers/elixir.pyx']),
     Extension('notmm.controllers.i18n',
-        ['lib/notmm/controllers/i18n.pyx'])
-    #Extension('notmm.dbapi.orm.dataproxy', \
-    #   ['lib/notmm/dbapi/orm/_dataproxy.pyx'])
+        ['lib/notmm/controllers/i18n.pyx']),
+    Extension('notmm.dbapi.orm.model', \
+       ['lib/notmm/dbapi/orm/model.pyx'])
     ]
 
 libs = find_packages(where='lib')
     
     # Minimal packages required when doing `python setup.py install`.
     install_requires=[
-        #'Django>=1.3',     # Maintainers should not need this :)
+        'Django>=1.10',     # Maintainers should not need this :)
         # iniparse
         'configobj>=4.7.2', # in notmm.utils.configparse (required)
         'argparse>=1.1',    # used by tools/httpserver.py
         'docutils>=0.8.1',  # HTMLPublisher (restapp)
         'cogen>=0.2.1',
         #'python-epoll>=1.0',# for epoll support; linux only?
-        'pytidylib>=0.2.1'
+        'pytidylib>=0.2.1',
+        'WebOb>=1.7.0'      # HTTPResponse,HTTPRequest
     ],
     # Optional but recommended packages. At least one or two
     # are required for most users.

File tests/apps/blogengine/model.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 # <LICENSE=ISC>
 # Default model classes for use in BlogEngine
 
-from notmm.dbapi.orm import ModelManager, RelationProxy, ClientStorageProxy
+from notmm.dbapi.orm import model, ClientStorageProxy
 from notmm.utils.django_settings import LazySettings
 
 _settings = LazySettings()
 
-db = ModelManager().setup('127.0.0.1:4343', backend=ClientStorageProxy)
-
-class AuthorManager(ModelManager):
-    objects = RelationProxy(db.Author)
+class Author(model.Model):
+    class Meta:
+        db_backend = ClientStorageProxy
+        db_addr = '127.0.0.1:4343'
 
-class CommentManager(ModelManager):
-    objects = RelationProxy(db.Comment)
-    
-    #def__new__(cls, *args, **kwargs):
-    #   cls.feedobj = cls.create_feed_obj(metaclass=RSSFeedGenerator)
-    #
-    #def create_feed_obj(self, metaclass):
-    #   pass
+class Comment(model.Model):
+    class Meta:
+        db_backend = ClientStorageProxy
+        db_addr = '127.0.0.1:4343'
 
-class MessageManager(ModelManager):
-    objects = RelationProxy(db.Message)
+class Message(model.Model):
+    class Meta:
+        db_backend = ClientStorageProxy
+        db_addr = '127.0.0.1:4343'
 
 # Generic voting Manager objects
 #class PollManager(object):

File tests/apps/blogengine/test_schema_migrate.py Modified

View file
  • Ignore whitespace
  • Hide word diff
 # schevo
 #from schevo.database2 import Database 
 from notmm.dbapi.orm import ZODBFileStorageProxy
-from model import AuthorManager, MessageManager, db
+from model import Author, Message
 
 class TutorialTestCase(unittest.TestCase):
 
     def setUp(self):
         super(TutorialTestCase, self).setUp()
-        self.db = db
+        self.db = Message().db
 
         # populate the database with sample data?
         # self.db.populate()
 
     def test_find_author(self):
         import schevo.query as Q
-        Person = AuthorManager.objects.get(username=u"Etienne Robillard")
+        Person = self.db.Author.findone(username=u"Etienne Robillard")
         #self.failUnlessEqual(isinstance(Person, db.Actor.__class__), True, type(Person))
-        blogentries = MessageManager.objects.find(author=Person)
+        blogentries = self.db.Message.find(author=Person)
         self.assertEqual(isinstance(blogentries, Q.ResultsList), True)
         #print blogentries

File tests/apps/moviereviews/model.py Added

View file
  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python
+from notmm.dbapi.orm import model, ClientStorageProxy
+
+class Message(model.Model):
+    class Meta:
+        db_backend = ClientStorageProxy
+        db_addr = '127.0.0.1:4343'

File tests/apps/moviereviews/test_model.py Modified

View file
  • Ignore whitespace
  • Hide word diff
     settings,
     ResponseClass
     )
-from notmm.dbapi.orm import model
+
+from model import Message
 
 class ModelTestCase(unittest.TestCase):
+    def setUp(self):
+        
 
-    def test_populate(self):
-        model.setup() 
-        models = model.get_models()
-        print models
+        self.db = Message().db
+        self.author = self.db.Author.findone(username="Etienne Robillard")
+        self.msg = Message(
+            messageid="12300", 
+            author=self.author, 
+            content="test")
+
+    def tearDown(self):
+        self.db.close()
 
+    #def test_populate(self):
+    #    model.setup() 
+    #    models = model.get_models()
+    #    #print models
+
+    def test_save(self):
+        if self.msg.db.conn._is_open:
+            print "Database connection is open"
+            try:
+                #import pdb; pdb.set_trace()
+                self.msg.save(commit=False)
+            except Exception, e:
+                print "rollback() called"
+                self.msg.db.backend.rollback()
+            print self.msg
+

File tests/django110/test_resolver.py Added

View file
  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#import os
+#import traceback
+import sys
+
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+from notmm.controllers.wsgi             import BaseController, WSGIController
+from notmm.utils.django_settings        import SettingsProxy
+from notmm.utils.wsgilib                import HTTPRequest, HTTPResponse
+from notmm.utils.django_compat          import RegexURLResolver, get_resolver
+from test_client                        import TestClient
+
+settings = SettingsProxy(autoload=True).settings
+class RegexUrlResolverTestCase(unittest.TestCase):
+    
+    def setUp(self):
+        self.resolver_func = get_resolver
+        self.urlconf = settings.ROOT_URLCONF
+    def test_get_resolver(self):
+        result = self.resolver_func(self.urlconf)
+        self.failIfEqual(result, None)
+
+if __name__ == '__main__':
+    unittest.main()

File tests/test_client.py Modified

View file
  • Ignore whitespace
  • Hide word diff
     
     def __init__(self, wsgi_app, environ={}, method='GET'):
         self.wsgi_app = wsgi_app
+        self.environ = environ
         try:
-            environ.update(getattr(wsgi_app, 'environ', self.default_wsgi_env))
+            self.environ.update(getattr(wsgi_app, 'environ', self.default_wsgi_env))
         except AttributeError:
             raise
         else:
-            self.environ = environ
             if not 'REQUEST_METHOD' in self.environ:
                 self.environ['REQUEST_METHOD'] = method
+            self.wsgi_app._environ = self.environ    
             self.method = method
             # init the base HTTPRequest instance
             try:
                 self.wsgi_app.registerWSGIHandlers(
                     wsgi_app.settings.CUSTOM_ERROR_HANDLERS
                     )
-                self.request = self.wsgi_app.init_request(self.environ)
-            except AttributeError:
+                assert hasattr(self.wsgi_app, 'init_request')
+                self.wsgi_app.init_request(self.environ)
+                self.request = self.wsgi_app.request
+                print "New test request object"
+            except AttributeError, e:
                 # Error initializing the WSGI request
                 self.request = None
-            self.urlconf = self.wsgi_app.urlconf
+            self.urlconf = getattr(self.wsgi_app, 'urlconf', None)
 
 class TestClient(TestApp):
 
             status_int = kwargs['status']
             assert isinstance(status_int, int), 'expected a integer value'
         
+        assert self.request != None
         response = self.wsgi_app.get_response(path_url, request=self.request)
         return response
 

File tests/test_resolver.py Deleted

  • Ignore whitespace
  • Hide word diff
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#import os
-#import traceback
-import sys
-
-try:
-    import unittest2 as unittest
-except ImportError:
-    import unittest
-
-from notmm.controllers.wsgi             import BaseController, WSGIController
-from notmm.utils.django_settings        import SettingsProxy
-from notmm.utils.wsgilib                import HTTPRequest, HTTPResponse
-from notmm.utils.django_compat          import RegexURLResolver, get_resolver
-from test_client                        import TestClient
-
-settings = SettingsProxy(autoload=True).settings
-class RegexUrlResolverTestCase(unittest.TestCase):
-    
-    def setUp(self):
-        self.resolver_func = get_resolver
-        self.urlconf = settings.ROOT_URLCONF
-    def test_get_resolver(self):
-        result = self.resolver_func(self.urlconf)
-        self.failIfEqual(result, None)
-
-if __name__ == '__main__':
-    unittest.main()