add initial model
authorFrédéric Péters <fpeters@0d.be>
Sun, 29 Dec 2019 13:30:22 +0000 (14:30 +0100)
committerFrédéric Péters <fpeters@0d.be>
Mon, 30 Dec 2019 08:35:50 +0000 (09:35 +0100)
chloro/phyll/__init__.py [new file with mode: 0644]
chloro/phyll/fields.py [new file with mode: 0644]
chloro/phyll/migrations/0001_initial.py [new file with mode: 0644]
chloro/phyll/migrations/__init__.py [new file with mode: 0644]
chloro/phyll/models.py [new file with mode: 0644]
chloro/settings.py
setup.py [new file with mode: 0644]

diff --git a/chloro/phyll/__init__.py b/chloro/phyll/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/chloro/phyll/fields.py b/chloro/phyll/fields.py
new file mode 100644 (file)
index 0000000..8440e4b
--- /dev/null
@@ -0,0 +1,46 @@
+# chloro - personal space
+# Copyright (C) 2019  Frederic Peters
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+import ckeditor.fields
+
+
+class RichTextField(ckeditor.fields.RichTextField):
+    def formfield(self, **kwargs):
+        defaults = {
+            'form_class': RichTextFormField,
+            'config_name': self.config_name,
+            'extra_plugins': self.extra_plugins,
+            'external_plugin_resources': self.external_plugin_resources,
+        }
+        defaults.update(kwargs)
+        return super(RichTextField, self).formfield(**defaults)
+
+
+class RichTextFormField(ckeditor.fields.RichTextFormField):
+    def clean(self, value):
+        value = super(RichTextFormField, self).clean(value)
+        if settings.LANGUAGE_CODE.startswith('fr-'):
+            # apply some basic typographic rules
+            value = value.replace('&laquo; ', '«\u202f')
+            value = value.replace('« ', '«\u202f')
+            value = value.replace(' &raquo;', '\u202f»')
+            value = value.replace(' »', '\u202f»')
+            value = value.replace(' :', '\u00a0:')
+            value = value.replace(' ;', '\u202f;')
+            value = value.replace(' !', '\u202f!')
+            value = value.replace(' ?', '\u202f?')
+        return value
diff --git a/chloro/phyll/migrations/0001_initial.py b/chloro/phyll/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..32c3af7
--- /dev/null
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.17 on 2019-12-29 13:29
+from __future__ import unicode_literals
+
+import chloro.phyll.fields
+from django.db import migrations, models
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('taggit', '0002_auto_20150616_2121'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Note',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('title', models.CharField(max_length=150, verbose_name='Title')),
+                ('slug', models.SlugField(max_length=150, verbose_name='Slug')),
+                ('text', chloro.phyll.fields.RichTextField(blank=True, null=True, verbose_name='Text')),
+                ('creation_timestamp', models.DateTimeField(auto_now_add=True)),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                (
+                    'tags',
+                    taggit.managers.TaggableManager(
+                        blank=True,
+                        help_text='A comma-separated list of tags.',
+                        through='taggit.TaggedItem',
+                        to='taggit.Tag',
+                        verbose_name='Tags',
+                    ),
+                ),
+            ],
+        ),
+    ]
diff --git a/chloro/phyll/migrations/__init__.py b/chloro/phyll/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/chloro/phyll/models.py b/chloro/phyll/models.py
new file mode 100644 (file)
index 0000000..587859d
--- /dev/null
@@ -0,0 +1,30 @@
+# chloro - personal space
+# Copyright (C) 2019  Frederic Peters
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.db import models, transaction
+from django.utils.translation import ugettext_lazy as _
+from taggit.managers import TaggableManager
+
+from .fields import RichTextField
+
+
+class Note(models.Model):
+    title = models.CharField(_('Title'), max_length=150)
+    slug = models.SlugField(_('Slug'), max_length=150)
+    text = RichTextField(_('Text'), blank=True, null=True)
+    tags = TaggableManager(_('Tags'), blank=True)
+    creation_timestamp = models.DateTimeField(auto_now_add=True)
+    last_update_timestamp = models.DateTimeField(auto_now=True)
index b29168d..2d8e8b6 100644 (file)
@@ -36,6 +36,8 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
+    'taggit',
+    'chloro.phyll',
 ]
 
 MIDDLEWARE = [
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..abcdbf4
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,157 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import os
+import re
+import subprocess
+import sys
+
+from setuptools.command.install_lib import install_lib as _install_lib
+from distutils.command.build import build as _build
+from distutils.command.sdist import sdist
+from distutils.cmd import Command
+from distutils.spawn import find_executable
+from setuptools import setup, find_packages
+
+
+class eo_sdist(sdist):
+    def run(self):
+        if os.path.exists('VERSION'):
+            os.remove('VERSION')
+        version = get_version()
+        with open('VERSION', 'w') as fd:
+            fd.write(version)
+        sdist.run(self)
+        if os.path.exists('VERSION'):
+            os.remove('VERSION')
+
+
+def get_version():
+    '''Use the VERSION, if absent generates a version with git describe, if not
+       tag exists, take 0.0- and add the length of the commit log.
+    '''
+    if os.path.exists('VERSION'):
+        with open('VERSION', 'r') as v:
+            return v.read()
+    if os.path.exists('.git'):
+        p = subprocess.Popen(
+            ['git', 'describe', '--dirty=.dirty', '--match=v*'],
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+        )
+        result = p.communicate()[0]
+        if p.returncode == 0:
+            result = result.decode('ascii').strip()[1:]  # strip spaces/newlines and initial v
+            if '-' in result:  # not a tagged version
+                real_number, commit_count, commit_hash = result.split('-', 2)
+                version = '%s.post%s+%s' % (real_number, commit_count, commit_hash)
+            else:
+                version = result
+            return version
+        else:
+            return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
+    return '0.0'
+
+
+class compile_translations(Command):
+    description = 'compile message catalogs to MO files via django compilemessages'
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        orig_dir = os.getcwd()
+        try:
+            from django.core.management import call_command
+
+            for path, dirs, files in os.walk('chloro'):
+                if 'locale' not in dirs:
+                    continue
+                curdir = os.getcwd()
+                os.chdir(os.path.realpath(path))
+                call_command('compilemessages')
+                os.chdir(curdir)
+        except ImportError:
+            sys.stderr.write('!!! Please install Django >= 1.4 to build translations\n')
+        os.chdir(orig_dir)
+
+
+class compile_scss(Command):
+    description = 'compile scss files into css files'
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        sass_bin = None
+        for program in ('sassc', 'sass'):
+            sass_bin = find_executable(program)
+            if sass_bin:
+                break
+        if not sass_bin:
+            raise CompileError(
+                'A sass compiler is required but none was found.  See sass-lang.com for choices.'
+            )
+
+        for path, dirnames, filenames in os.walk('chloro'):
+            for filename in filenames:
+                if not filename.endswith('.scss'):
+                    continue
+                if filename.startswith('_'):
+                    continue
+                subprocess.check_call(
+                    [
+                        sass_bin,
+                        '%s/%s' % (path, filename),
+                        '%s/%s' % (path, filename.replace('.scss', '.css')),
+                    ]
+                )
+
+
+class build(_build):
+    sub_commands = [('compile_translations', None), ('compile_scss', None)] + _build.sub_commands
+
+
+class install_lib(_install_lib):
+    def run(self):
+        self.run_command('compile_translations')
+        _install_lib.run(self)
+
+
+setup(
+    name='chloro',
+    version=get_version(),
+    description='Content Manager',
+    author='Frederic Peters',
+    author_email='fpeters@0d.be',
+    packages=find_packages(exclude=['tests']),
+    include_package_data=True,
+    scripts=('manage.py',),
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Environment :: Web Environment',
+        'Framework :: Django',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+    ],
+    install_requires=['django>=1.11, <1.12', 'django-ckeditor<=4.5.3', 'django-taggit',],
+    zip_safe=False,
+    cmdclass={
+        'build': build,
+        'compile_scss': compile_scss,
+        'compile_translations': compile_translations,
+        'install_lib': install_lib,
+        'sdist': eo_sdist,
+    },
+)