4 Commits 1ed9c9effd ... 25902e0c4a

Author SHA1 Message Date
  Kapustlo 25902e0c4a Updated version to 3.3.0 2 years ago
  Kapustlo c7c9033fee Added git config support 2 years ago
  Kapustlo 8e1614ba6b Optimized process.py module 2 years ago
  Kapustlo 6b50c08fdf Added pytest to deps 2 years ago

+ 5 - 1
build_django/__init__.py

@@ -2,7 +2,7 @@ from argparse import ArgumentParser
 
 
 __author__ = 'Kapustlo'
 __author__ = 'Kapustlo'
 
 
-__version__ = '3.2.0'
+__version__ = '3.3.0'
 
 
 parser: ArgumentParser = ArgumentParser(description='Build Django project')
 parser: ArgumentParser = ArgumentParser(description='Build Django project')
 
 
@@ -31,3 +31,7 @@ parser.add_argument('--packages', dest='packages', nargs='+', help='Additional p
 parser.add_argument('--no-compile', dest='no_compile', action='store_true', required=False, help='pip: Do not compile Python source files to bytecode')
 parser.add_argument('--no-compile', dest='no_compile', action='store_true', required=False, help='pip: Do not compile Python source files to bytecode')
 
 
 parser.add_argument('--use-ssl', dest='us_ssl', action='store_true', required=False, help='Enable SSL support for reverse proxy')
 parser.add_argument('--use-ssl', dest='us_ssl', action='store_true', required=False, help='Enable SSL support for reverse proxy')
+
+parser.add_argument('--email', dest='email', required=False, default='', type=str, help='Git email if no global is specified')
+
+parser.add_argument('--username', dest='username', required=False, default='', type=str, help='Git name if no global is specified')

+ 7 - 2
build_django/__main__.py

@@ -1,6 +1,7 @@
 import sys
 import sys
 import venv
 import venv
 import asyncio
 import asyncio
+from typing import cast
 from pathlib import Path
 from pathlib import Path
 from shlex import quote
 from shlex import quote
 
 
@@ -26,8 +27,6 @@ async def exec():
     else:
     else:
         print('Project directory found')
         print('Project directory found')
 
 
-    repo = Repo(project_path)
-
     name = args.name
     name = args.name
 
 
     print('Creating Django project...')
     print('Creating Django project...')
@@ -86,7 +85,11 @@ async def exec():
         )
         )
     ]
     ]
 
 
+    repo = cast(Repo, None)  # In order to fix linter errors
+
     if args.git:
     if args.git:
+        repo = Repo(project_path)
+
         tasks.append(repo.init())
         tasks.append(repo.init())
 
 
     print('Creating files...')
     print('Creating files...')
@@ -98,6 +101,8 @@ async def exec():
     tasks = []
     tasks = []
 
 
     if args.git and args.commit:
     if args.git and args.commit:
+        await repo.setup(args.email, args.username)
+
         await repo.add(('.',), _v=True)
         await repo.add(('.',), _v=True)
 
 
         task = repo.commit(args.commit_message, _v=True)
         task = repo.commit(args.commit_message, _v=True)

+ 54 - 10
build_django/utils/git.py

@@ -1,27 +1,71 @@
-from typing import Union, Iterable
+import asyncio
 from shlex import quote
 from shlex import quote
-from pathlib import Path
+from subprocess import SubprocessError
+from dataclasses import dataclass
 from asyncio.subprocess import Process
 from asyncio.subprocess import Process
+from typing import Iterable, Any, cast
 
 
 from .shell import Shell
 from .shell import Shell
 
 
 
 
-class Repo(Shell):
-    pwd: Path
+class GitShell(Shell):
+    async def cmd(self, args, **kwargs) -> Process:
+        params = self._kwargs_to_params(**kwargs)
+
+        return await self.run(('git', *args, *params))
+
+
+@dataclass
+class ConfigSection(GitShell):
+    section: str
+    
+    async def value(self, name: str) -> str:
+        try:
+            process = await self.cmd(('config', '--get', f'{self.section}.{name}'))
+        except SubprocessError:
+            return ''
 
 
-    def __init__(self, path: Union[str, Path]):
-        super().__init__()
+        return cast(str, process.stdout)
 
 
-        self.cd(path)
+    async def set(self, name: str, value: Any) -> Any:
+        await self.cmd(('config', f'{self.section}.{name}', quote(value)))
 
 
+        return self
+
+
+class Config(GitShell):
+    def section(self, name: str) -> ConfigSection:
+        return ConfigSection(self.pwd, name)
+
+
+class Repo(GitShell):
     @property
     @property
     def initialized(self) -> bool:
     def initialized(self) -> bool:
         return (self.pwd / '.git').exists()
         return (self.pwd / '.git').exists()
 
 
-    async def cmd(self, args, **kwargs) -> Process:
-        params = self._kwargs_to_params(**kwargs)
+    @property
+    def config(self) -> Config:
+        return Config(self.pwd)
+
+    async def setup(self, email: str = '', name: str = ''):
+        tasks = []
+
+        section = self.config.section('user')
+
+        cur_name = await section.value('name')
+
+        if not cur_name:
+            tasks.append(section.set('name', name))
+
+        cur_email = await section.value('email')
+
+        if not cur_email:
+            tasks.append(section.set('email', email))
+
+        await asyncio.gather(*tasks)
+
+        return self
 
 
-        return await self.run(('git', *args, *params))
 
 
     async def init(self) -> Process:
     async def init(self) -> Process:
         if self.initialized:
         if self.initialized:

+ 7 - 13
build_django/utils/process.py

@@ -1,12 +1,10 @@
-import sys
 import asyncio
 import asyncio
 from pathlib import Path
 from pathlib import Path
-from shlex import quote
 from subprocess import SubprocessError
 from subprocess import SubprocessError
 from asyncio.subprocess import PIPE, Process
 from asyncio.subprocess import PIPE, Process
 from typing import Union, Iterable
 from typing import Union, Iterable
 
 
-SYS_ENCODING = sys.getdefaultencoding()
+from . import system
 
 
 
 
 async def run_cmd(
 async def run_cmd(
@@ -15,18 +13,14 @@ async def run_cmd(
     **kwargs
     **kwargs
 ) -> Process:
 ) -> Process:
     if cwd:
     if cwd:
-        args = (
-            'cd',
-            quote(str(cwd)),
-            '&&',
-            *args
-        )
+        cwd = str(cwd)
 
 
     cmd = ' '.join(args)
     cmd = ' '.join(args)
 
 
     kwargs = {
     kwargs = {
         'stdout': PIPE,
         'stdout': PIPE,
         'stderr': PIPE,
         'stderr': PIPE,
+        'cwd': cwd,
         **kwargs
         **kwargs
     }
     }
 
 
@@ -34,10 +28,7 @@ async def run_cmd(
 
 
     result = await process.communicate()
     result = await process.communicate()
 
 
-    out, err = [
-        item.decode(SYS_ENCODING)
-        if isinstance(item, bytes) else item for item in result
-    ]
+    out, err = result
 
 
     code = process.returncode
     code = process.returncode
 
 
@@ -45,6 +36,9 @@ async def run_cmd(
         raise SubprocessError(f'{code}: {err}')
         raise SubprocessError(f'{code}: {err}')
 
 
     if out:
     if out:
+        if isinstance(out, bytes):
+            out = system.decode(out)
+
         print(out)
         print(out)
 
 
     return process
     return process

+ 8 - 2
build_django/utils/shell.py

@@ -1,12 +1,18 @@
 from pathlib import Path
 from pathlib import Path
+from dataclasses import dataclass
 from typing import Union, Iterable
 from typing import Union, Iterable
 from asyncio.subprocess import Process
 from asyncio.subprocess import Process
 
 
 from .process import run_cmd
 from .process import run_cmd
 
 
 
 
+@dataclass
 class Shell:
 class Shell:
-    pwd: Union[Path, None] = None
+    _pwd: Union[str, Path, None]
+    
+    @property
+    def pwd(self) -> Path:
+        return Path('./' if self._pwd is None else self._pwd).absolute()
 
 
     def _kwargs_to_params(self, **kwargs: dict[str, str]) -> list[str]:
     def _kwargs_to_params(self, **kwargs: dict[str, str]) -> list[str]:
         result = []
         result = []
@@ -29,7 +35,7 @@ class Shell:
         if path.is_file():
         if path.is_file():
             raise ValueError(f'{path} is a file')
             raise ValueError(f'{path} is a file')
 
 
-        self.pwd = path
+        self._pwd = path
 
 
         return self
         return self
 
 

+ 6 - 0
build_django/utils/system.py

@@ -0,0 +1,6 @@
+from sys import getdefaultencoding
+
+SYS_ENCODING = getdefaultencoding()
+
+def decode(b: bytes) -> str:
+    return b.decode(SYS_ENCODING)

+ 9 - 1
requirements.txt

@@ -1,6 +1,6 @@
-wheel
 aiofiles==22.1.0
 aiofiles==22.1.0
 asgiref==3.5.0
 asgiref==3.5.0
+attrs==22.1.0
 bleach==5.0.0
 bleach==5.0.0
 certifi==2021.10.8
 certifi==2021.10.8
 cffi==1.15.0
 cffi==1.15.0
@@ -9,13 +9,20 @@ commonmark==0.9.1
 cryptography==36.0.2
 cryptography==36.0.2
 Django==4.0.4
 Django==4.0.4
 docutils==0.18.1
 docutils==0.18.1
+exceptiongroup==1.0.4
 idna==3.3
 idna==3.3
 importlib-metadata==4.11.3
 importlib-metadata==4.11.3
+iniconfig==1.1.1
 jeepney==0.8.0
 jeepney==0.8.0
 keyring==23.5.0
 keyring==23.5.0
+packaging==21.3
 pkginfo==1.8.2
 pkginfo==1.8.2
+pluggy==1.0.0
 pycparser==2.21
 pycparser==2.21
 Pygments==2.11.2
 Pygments==2.11.2
+pyparsing==3.0.9
+pytest==7.2.0
+pytest-asyncio==0.20.2
 readme-renderer==35.0
 readme-renderer==35.0
 requests==2.27.1
 requests==2.27.1
 requests-toolbelt==0.9.1
 requests-toolbelt==0.9.1
@@ -24,6 +31,7 @@ rich==12.2.0
 SecretStorage==3.3.2
 SecretStorage==3.3.2
 six==1.16.0
 six==1.16.0
 sqlparse==0.4.2
 sqlparse==0.4.2
+tomli==2.0.1
 twine==4.0.0
 twine==4.0.0
 urllib3==1.26.9
 urllib3==1.26.9
 webencodings==0.5.1
 webencodings==0.5.1

+ 1 - 1
tests/manage.sh

@@ -11,7 +11,7 @@ then
 
 
   if [[ $2 = "" ]]
   if [[ $2 = "" ]]
   then
   then
-    time python -m build_django --dir "./tests/test_projects/$(openssl rand -hex 20)" --git --commit --debug --migrate --no-compile --use-ssl --commit-message "Test commit"  test_project
+    time python -m build_django --dir "./tests/test_projects/$(openssl rand -hex 20)" --git --commit --debug --migrate --no-compile --use-ssl --commit-message "Test commit" --email "test@example.com" --username "Kapustlo"  test_project
   fi
   fi
 elif [[ $1 = "clear" ]]
 elif [[ $1 = "clear" ]]
 then
 then