fanch 1 рік тому
коміт
bbe12d74c3
38 змінених файлів з 646 додано та 0 видалено
  1. 3 0
      README.md
  2. 16 0
      main.py
  3. 25 0
      setup.cfg
  4. 57 0
      setup.py
  5. 0 0
      src/pytemplate/__init__.py
  6. 3 0
      src/pytemplate/__main__.py
  7. 35 0
      src/pytemplate/cmdline.py
  8. 2 0
      src/pytemplate/pytemplate
  9. 7 0
      src/pytemplate/resources/__init__.py
  10. 7 0
      src/pytemplate/resources/django/.gitignore
  11. 1 0
      src/pytemplate/resources/django/MANIFEST.in
  12. 3 0
      src/pytemplate/resources/django/README.md
  13. 22 0
      src/pytemplate/resources/django/manage.py
  14. 25 0
      src/pytemplate/resources/django/setup.cfg
  15. 58 0
      src/pytemplate/resources/django/setup.py
  16. 0 0
      src/pytemplate/resources/django/src/%(module)s/__init__.py
  17. 0 0
      src/pytemplate/resources/django/src/%(module)s/app/__init__.py
  18. 3 0
      src/pytemplate/resources/django/src/%(module)s/app/admin.py
  19. 6 0
      src/pytemplate/resources/django/src/%(module)s/app/apps.py
  20. 0 0
      src/pytemplate/resources/django/src/%(module)s/app/models/__init__.py
  21. 0 0
      src/pytemplate/resources/django/src/%(module)s/app/views/__init__.py
  22. 16 0
      src/pytemplate/resources/django/src/%(module)s/asgi.py
  23. 0 0
      src/pytemplate/resources/django/src/%(module)s/scripts/__init__.py
  24. 67 0
      src/pytemplate/resources/django/src/%(module)s/settings/__init__.py
  25. 37 0
      src/pytemplate/resources/django/src/%(module)s/settings/prod.py
  26. 22 0
      src/pytemplate/resources/django/src/%(module)s/urls.py
  27. 16 0
      src/pytemplate/resources/django/src/%(module)s/wsgi.py
  28. 0 0
      src/pytemplate/resources/django/tests/__init__.py
  29. 0 0
      src/pytemplate/resources/django/tests/test_a.py
  30. 10 0
      src/pytemplate/resources/empty/.gitignore
  31. 1 0
      src/pytemplate/resources/empty/MANIFEST.in
  32. 3 0
      src/pytemplate/resources/empty/README.md
  33. 25 0
      src/pytemplate/resources/empty/setup.cfg
  34. 54 0
      src/pytemplate/resources/empty/setup.py
  35. 0 0
      src/pytemplate/resources/empty/src/%(module)s/__init__.py
  36. 0 0
      src/pytemplate/resources/empty/tests/__init__.py
  37. 0 0
      src/pytemplate/resources/empty/tests/test_a.py
  38. 122 0
      src/pytemplate/template.py

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# Listes
+
+A short description of the project.

+ 16 - 0
main.py

@@ -0,0 +1,16 @@
+# This is a sample Python script.
+
+# Press Maj+F10 to execute it or replace it with your code.
+# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
+
+
+def print_hi(name):
+    # Use a breakpoint in the code line below to debug your script.
+    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.
+
+
+# Press the green button in the gutter to run the script.
+if __name__ == '__main__':
+    print_hi('PyCharm')
+
+# See PyCharm help at https://www.jetbrains.com/help/pycharm/

+ 25 - 0
setup.cfg

@@ -0,0 +1,25 @@
+[coverage:run]
+source = src
+
+[coverage:report]
+ignore_errors = False
+show_missing = True
+
+[coverage:xml]
+output = coverage.xml
+
+[tool:pytest]
+markers =
+    noci: marks tests so that they are not executed in continuous integration (jenkins)
+testpaths = tests/
+junit_family = xunit2
+console_output_style = progress
+log_level = DEBUG
+DJANGO_SETTINGS_MODULE = tests.settings
+
+[build_sphinx]
+; python setup.py build_sphinx  # Generate the HTML documentation in dist/docs/html
+source-dir = docs/source
+build-dir = dist/docs
+all_files = 1
+

+ 57 - 0
setup.py

@@ -0,0 +1,57 @@
+from setuptools import setup, find_packages
+from pathlib import Path
+
+install_requires = [
+]
+
+tests_require = [
+    "mkfab"
+]
+
+def get_files(path):
+    root = Path(path)
+    queue = [root]
+    ret = []
+    while queue:
+        curr = queue.pop()
+        for file in curr.iterdir():
+            if file.is_file():
+                ret.append(str(file))
+            else:
+                queue.append(file)
+    return ret
+
+
+setup(
+    name="pytemplate",
+    version="0.1.1",
+    description="A short description of the project.",
+    author="François GAUTRAIS",
+    author_email="Your email",
+    keywords="CADB FGAU",
+    install_requires=install_requires,
+    packages=find_packages("src"),
+    include_package_data=True,
+    zip_safe=False,
+    data_files=[
+        ("", ["README.md"]),
+        ("data", get_files("src/pytemplate/resources"))
+    ],
+
+    test_suite="tests",
+    tests_require=tests_require,
+    extras_require={
+        "test": tests_require,
+        "pylint": ["pylint"],
+    },
+    scripts=[
+        "src/pytemplate/pytemplate"
+    ],
+
+    entry_points={
+        "console_scripts": [
+        ]
+    },
+    package_dir={"": "src"},
+)
+

+ 0 - 0
src/pytemplate/__init__.py


+ 3 - 0
src/pytemplate/__main__.py

@@ -0,0 +1,3 @@
+from pytemplate.cmdline import Args
+
+app = Args.parse()

+ 35 - 0
src/pytemplate/cmdline.py

@@ -0,0 +1,35 @@
+import argparse
+import sys
+from pathlib import Path
+
+from pytemplate.template import Template
+
+
+class Args(argparse.ArgumentParser):
+
+    def __init__(self):
+        super().__init__()
+        self.add_argument("--create", "-c", help="Créer un nouveau template", action="store_true")
+        self.add_argument("--name", "-n", help="Nom du projet")
+        self.add_argument("--module", "-m", help = "Nom du module")
+        self.add_argument("target", help="Nom du template (ou dossier du template à creer avec --create)")
+        self.add_argument("output", help="Dossier de création (ou nom du nouveau template --create)")
+
+    @classmethod
+    def parse(cls, args = None):
+        self = cls()
+        if args is None: args = sys.argv[1:]
+
+        ret = self.parse_args(args)
+        data = {
+            "name" : ret.name,
+            "module" : ret.module
+        }
+
+        template = Template(ret.target)
+
+        if ret.create:
+            template.mk_template(ret.output, data)
+        else:
+            template.instanciate(ret.output, data)
+

+ 2 - 0
src/pytemplate/pytemplate

@@ -0,0 +1,2 @@
+#!/bin/bash
+python3 -m pytemplate $*

+ 7 - 0
src/pytemplate/resources/__init__.py

@@ -0,0 +1,7 @@
+
+
+from pathlib import Path
+
+def get_resources_path(path):
+    return  Path(__file__).absolute().parent / path
+

+ 7 - 0
src/pytemplate/resources/django/.gitignore

@@ -0,0 +1,7 @@
+/.idea/vcs.xml
+/.idea/inspectionProfiles/profiles_settings.xml
+/.idea/*.iml
+/build/
+/run/
+**.pyc
+**.sqlite3

+ 1 - 0
src/pytemplate/resources/django/MANIFEST.in

@@ -0,0 +1 @@
+recursive-include src *.*

+ 3 - 0
src/pytemplate/resources/django/README.md

@@ -0,0 +1,3 @@
+# %(name)s
+
+A short description of the project.

+ 22 - 0
src/pytemplate/resources/django/manage.py

@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    """Run administrative tasks."""
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', '%(module)s.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+    main()

+ 25 - 0
src/pytemplate/resources/django/setup.cfg

@@ -0,0 +1,25 @@
+[coverage:run]
+source = src
+
+[coverage:report]
+ignore_errors = False
+show_missing = True
+
+[coverage:xml]
+output = coverage.xml
+
+[tool:pytest]
+markers =
+    noci: marks tests so that they are not executed in continuous integration (jenkins)
+testpaths = tests/
+junit_family = xunit2
+console_output_style = progress
+log_level = DEBUG
+DJANGO_SETTINGS_MODULE = tests.settings
+
+[build_sphinx]
+; python setup.py build_sphinx  # Generate the HTML documentation in dist/docs/html
+source-dir = docs/source
+build-dir = dist/docs
+all_files = 1
+

+ 58 - 0
src/pytemplate/resources/django/setup.py

@@ -0,0 +1,58 @@
+from setuptools import setup, find_packages
+from pathlib import Path
+
+install_requires = [
+    "django",
+    "django-cors-headers",
+    "djangotools"
+]
+
+tests_require = [
+    "mkfab",
+    "pytest",
+    "pytest-django"
+]
+
+def get_files(path):
+    root = Path(path)
+    queue = [root]
+    ret = []
+    while queue:
+        curr = queue.pop()
+        for file in curr.iterdir():
+            if file.is_file():
+                ret.append(str(file))
+            else:
+                queue.append(file)
+    return ret
+
+
+setup(
+    name="%(name)s",
+    version="0.1.1",
+    description="A short description of the project.",
+    author="François GAUTRAIS",
+    install_requires=install_requires,
+    packages=find_packages("src"),
+    include_package_data=True,
+    zip_safe=False,
+    data_files=[
+        ("", ["README.md"]),
+    ],
+
+    test_suite="tests",
+    tests_require=tests_require,
+    extras_require={
+        "test": tests_require,
+        "pylint": ["pylint"],
+    },
+    scripts=[
+    ],
+
+    entry_points={
+        "console_scripts": [
+        ]
+    },
+    package_dir={"": "src"},
+)
+

+ 0 - 0
src/pytemplate/resources/django/src/%(module)s/__init__.py


+ 0 - 0
src/pytemplate/resources/django/src/%(module)s/app/__init__.py


+ 3 - 0
src/pytemplate/resources/django/src/%(module)s/app/admin.py

@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.

+ 6 - 0
src/pytemplate/resources/django/src/%(module)s/app/apps.py

@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AppConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = '%(module)s.app'

+ 0 - 0
src/pytemplate/resources/django/src/%(module)s/app/models/__init__.py


+ 0 - 0
src/pytemplate/resources/django/src/%(module)s/app/views/__init__.py


+ 16 - 0
src/pytemplate/resources/django/src/%(module)s/asgi.py

@@ -0,0 +1,16 @@
+"""
+ASGI config for %(name)s project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', '%(module)s.settings')
+
+application = get_asgi_application()

+ 0 - 0
src/pytemplate/resources/django/src/%(module)s/scripts/__init__.py


+ 67 - 0
src/pytemplate/resources/django/src/%(module)s/settings/__init__.py

@@ -0,0 +1,67 @@
+"""
+Django settings for %(name)s project.
+
+Generated by 'django-admin startproject' using Django 4.2.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.2/ref/settings/
+"""
+
+from pathlib import Path
+
+from django.core.management.utils import get_random_secret_key
+from djangotools.config import load_settings
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+DEBUG = True
+
+
+
+# Application definition
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    "%(module)s.app",
+    "djangotools"
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'corsheaders.middleware.CorsMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+
+
+WSGI_APPLICATION = '%(module)s.wsgi.application'
+
+
+
+# djangotools
+COMMANDS_MODULES=["djangotools.cmdline.commands", "%(module)s.scripts.commands"]
+CONTEXT_MODULES=[]
+VIEWS_MODULES=["djangotools.views", "%(module)s.app.views"]
+
+LOGIN_URL="login"
+LOGOUT_URL="disconnect"
+AUTH_URL="auth"
+CONTEXT_URL="context/<str:name>"
+LOGIN_TEMPLATE="login"
+app_dir = BASE_DIR.parent.parent / "data"
+
+
+CONFIG = load_settings(globals())

+ 37 - 0
src/pytemplate/resources/django/src/%(module)s/settings/prod.py

@@ -0,0 +1,37 @@
+"""
+Django settings for %(name)s project.
+
+Generated by 'django-admin startproject' using Django 4.2.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.2/ref/settings/
+"""
+from djangotools.config import NoConfigLoader
+
+with NoConfigLoader():
+    from %(module)s.settings import *
+
+DEBUG=False
+
+CRON = [
+    # {
+    #     "name" : "backup",
+    #     "timers" : [
+    #     ]
+    # },
+    # {
+    #     "name" : "update",
+    #     "timers" : [
+    #         ("daily", 0),
+    #         ("daily", 6),
+    #         ("daily", 12),
+    #     ]
+    # }
+]
+
+HOSTNAME="localhost:8000"
+
+CONFIG = load_settings(globals())

+ 22 - 0
src/pytemplate/resources/django/src/%(module)s/urls.py

@@ -0,0 +1,22 @@
+"""
+URL configuration for %(name)s project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/4.2/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path
+
+urlpatterns = [
+    path('admin/', admin.site.urls),
+]

+ 16 - 0
src/pytemplate/resources/django/src/%(module)s/wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for %(name)s project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', '%(module)s.settings')
+
+application = get_wsgi_application()

+ 0 - 0
src/pytemplate/resources/django/tests/__init__.py


+ 0 - 0
src/pytemplate/resources/django/tests/test_a.py


+ 10 - 0
src/pytemplate/resources/empty/.gitignore

@@ -0,0 +1,10 @@
+**/node_modules/
+**/secret
+**/build
+**/run
+**/*-info/
+**/.idea/
+**.pyc
+**.log
+**.sqlite3
+**/dist

+ 1 - 0
src/pytemplate/resources/empty/MANIFEST.in

@@ -0,0 +1 @@
+recursive-include src *.*

+ 3 - 0
src/pytemplate/resources/empty/README.md

@@ -0,0 +1,3 @@
+# %(name)s
+
+A short description of the project.

+ 25 - 0
src/pytemplate/resources/empty/setup.cfg

@@ -0,0 +1,25 @@
+[coverage:run]
+source = src
+
+[coverage:report]
+ignore_errors = False
+show_missing = True
+
+[coverage:xml]
+output = coverage.xml
+
+[tool:pytest]
+markers =
+    noci: marks tests so that they are not executed in continuous integration (jenkins)
+testpaths = tests/
+junit_family = xunit2
+console_output_style = progress
+log_level = DEBUG
+DJANGO_SETTINGS_MODULE = tests.settings
+
+[build_sphinx]
+; python setup.py build_sphinx  # Generate the HTML documentation in dist/docs/html
+source-dir = docs/source
+build-dir = dist/docs
+all_files = 1
+

+ 54 - 0
src/pytemplate/resources/empty/setup.py

@@ -0,0 +1,54 @@
+from setuptools import setup, find_packages
+from pathlib import Path
+
+install_requires = [
+]
+
+tests_require = [
+    "mkfab",
+    "pytest"
+]
+
+def get_files(path):
+    root = Path(path)
+    queue = [root]
+    ret = []
+    while queue:
+        curr = queue.pop()
+        for file in curr.iterdir():
+            if file.is_file():
+                ret.append(str(file))
+            else:
+                queue.append(file)
+    return ret
+
+
+setup(
+    name="%(name)s",
+    version="0.1.1",
+    description="A short description of the project.",
+    author="François GAUTRAIS",
+    install_requires=install_requires,
+    packages=find_packages("src"),
+    include_package_data=True,
+    zip_safe=False,
+    data_files=[
+        ("", ["README.md"]),
+    ],
+
+    test_suite="tests",
+    tests_require=tests_require,
+    extras_require={
+        "test": tests_require,
+        "pylint": ["pylint"],
+    },
+    scripts=[
+    ],
+
+    entry_points={
+        "console_scripts": [
+        ]
+    },
+    package_dir={"": "src"},
+)
+

+ 0 - 0
src/pytemplate/resources/empty/src/%(module)s/__init__.py


+ 0 - 0
src/pytemplate/resources/empty/tests/__init__.py


+ 0 - 0
src/pytemplate/resources/empty/tests/test_a.py


+ 122 - 0
src/pytemplate/template.py

@@ -0,0 +1,122 @@
+import json
+import shutil
+from collections import OrderedDict
+from pathlib import Path
+
+from src.pytemplate.resources import get_resources_path
+
+
+
+
+class Template:
+
+    variables = OrderedDict([
+        ("name", ("Nom du projet", )),
+        ("module", ("Nom du module", lambda data: data["name"].lower())),
+    ])
+
+    def __init__(self, root):
+        self.root = Path(root)
+
+        try:
+            self.keys = json.loads((self.root / ".template_keys").read_text())
+        except FileNotFoundError:
+            self.keys = []
+        except json.decoder.JSONDecodeError:
+            self.keys = []
+
+
+    def list_files(self):
+        queue = [self.root]
+        files = []
+        while queue:
+            curr = queue.pop(0)
+            for file in curr.iterdir():
+                if file.is_file() and file.name != ".template_keys":
+                    files.append(file)
+                elif not file.name == ".idea":
+                    files.append(file)
+                    queue.append(file)
+        return files
+
+
+    def _prompt(self, data):
+        if not data: data = {}
+        for name, (help, *args) in self.variables.items():
+            if data.get(name) is not None: continue
+            default_value = ""
+            if args:
+                default_value = f"[{args[0](data)}]"
+            ret = input(f"{help}{default_value}: ").split()
+            if ret: ret = ret[0]
+            if default_value and not ret:
+                ret = default_value
+            data[name] = ret
+        data["name_lower"] = data["name"].lower()
+        return data
+
+    def _str_replace(self, content, data):
+        assert isinstance(content, str)
+        for name, to_find in data.items():
+            content = content.replace(to_find, f"%({name})s")
+        return content
+
+    def mk_template(self, name, data):
+        data = self._prompt(data)
+        out_dir = get_resources_path(name)
+        if out_dir.exists():
+            shutil.rmtree(out_dir)
+
+        out_dir.mkdir(exist_ok=True, parents=True)
+        #data = {v: k for k,v in data.items()}
+
+
+        for file in self.list_files():
+            file: Path
+            out_file = out_dir / self._str_replace(str(file.relative_to(self.root)), data)
+            out_file.parent.mkdir(exist_ok=True, parents=True)
+            if file.is_dir():
+                file.mkdir(exist_ok=True, parents=True)
+                continue
+            try:
+                file_in = file.read_text()
+            except UnicodeDecodeError:
+                shutil.copy(file, out_file)
+                continue
+            file_in = self._str_replace(file_in, data)
+
+            out_file.write_text(file_in)
+
+    def instanciate(self, output, data):
+        output = Path(output)
+        if not self.root.is_absolute():
+            self.root = get_resources_path(str(self.root))
+        if output.exists() and len(list(output.iterdir())):
+            print(f"Impossible d'intancier le template {self.root.name} le dossier {output} existe")
+            exit(-1)
+        if not self.root.exists():
+            print(f"Impossible d'intancier le template {self.root.name} est introuvable")
+            exit(-1)
+
+        output.mkdir(exist_ok=True, parents=True)
+
+        data = self._prompt(data)
+
+        for file in self.list_files():
+            file: Path
+            file.parent.mkdir(exist_ok=True, parents=True)
+            out_file = output / (str(file.relative_to(self.root)) % data)
+            if file.is_dir():
+                out_file.mkdir(exist_ok=True, parents=True)
+                continue
+            try:
+                file_in = file.read_text() % data
+            except UnicodeDecodeError:
+                shutil.copy(file, out_file)
+                continue
+            file_in = file_in % data
+            out_file.write_text(file_in)
+
+
+
+