diff --git a/.gitignore b/.gitignore
index 1d5e709..2c82418 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,5 +73,3 @@ venv/
# vscodium
*vscode/
-# JetBrains
-.idea/
\ No newline at end of file
diff --git a/CHANGELOG.MD b/CHANGELOG.MD
index 685bcbd..97bc319 100644
--- a/CHANGELOG.MD
+++ b/CHANGELOG.MD
@@ -28,6 +28,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Unused normalize.css file
- Identical links assigned in each translation file -->
+## [0.3.1] - 2024-04-14
+
+### Added
+- Easier way to add templates.
+- New templates : Data Science
+
+### Fixed
+- Error on listing templates.
+
+### Changed
+- Refactoring to introduce the TUI (interactive mode)
+
+
## [0.3.0] - 2023-08-05
### Added
@@ -71,6 +84,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved error reporting
### Fixed
+
- Fixed Issue [#8](https://github.com/HushmKun/Artec/issues/8)
- Fixed error building structure if the source starts with a file.
diff --git a/README.md b/README.md
index 795cdac..743b68b 100644
--- a/README.md
+++ b/README.md
@@ -23,17 +23,21 @@ Create a JSON file to match the folder structure you desire
$ vim structure.json
# Paste the below into your file and modify as you desire
-[
- {"folder": "{}"}, # Use '{}' to be replaced with project name.
- {"file": "{}/__init__.py"},
- {"folder": "test"},
- {"file": "test/__init__.py"},
- {"file": "README.md"},
- {"file": "LICENSE"},
- {"file": "setup.py"},
- {"file": "setup.cfg"},
- {"file": "pyproject.toml"},
-]
+{
+ "folders": [
+ "{}",
+ "test"
+ ],
+ "files": [
+ "{}/__init__.py",
+ "test/__init__.py",
+ "README.md",
+ "LICENSE",
+ "setup.py",
+ "pyproject.toml"
+ ]
+}
+
```
How to execute
```
@@ -64,141 +68,14 @@ Examples:
```
## Templates
-
- Python
-
-Project Named Artec
-```
-artec
-├── artec
-│ └── __main__.py
-├── test
-│ └── __init__.py
-├── LICENSE
-├── pyproject.toml
-├── README.md
-├── setup.cfg
-└── setup.py
-
-2 directories, 7 files
-```
-
-
-
- Flask
-
-Project Named flaskr
-```
-flaskr
-.
-├── flaskr
-│ ├── auth.py
-│ ├── blog
-│ │ ├── create.html
-│ │ ├── index.html
-│ │ └── update.html
-│ ├── blog.py
-│ ├── db.py
-│ ├── __init__.py
-│ ├── schema.py
-│ ├── static
-│ │ └── style.css
-│ └── templates
-│ ├── auth
-│ │ ├── login.html
-│ │ └── register.html
-│ └── base.html
-├── LICENSE
-├── pyproject.toml
-├── README.md
-├── setup.py
-└── test
- ├── conftest.py
- ├── data.sql
- ├── __init__.py
- ├── test_auth.py
- ├── test_blog.py
- └── test_db.py
-
-7 directories, 22 files
-```
-
-
- Node.Js
-
-Project Named Node
-```
-Node
-├── LICENSE
-├── package.json
-├── package-lock.json
-├── README.md
-└── src
- ├── api
- │ ├── controllers
- │ │ └── user
- │ │ ├── auth
- │ │ │ ├── forgot-password.js
- │ │ │ ├── login.js
- │ │ │ ├── logout.js
- │ │ │ ├── refresh-token.js
- │ │ │ ├── register.js
- │ │ │ ├── send-verification-code.js
- │ │ │ └── verify-email.js
- │ │ ├── delete-user.js
- │ │ ├── edit
- │ │ │ ├── change-password.js
- │ │ │ └── edit-user.js
- │ │ ├── get-user.js
- │ │ └── index.js
- │ ├── middlewares
- │ │ ├── auth
- │ │ │ ├── check-auth.js
- │ │ │ └── check-authority.js
- │ │ ├── image-upload.js
- │ │ ├── index.js
- │ │ ├── object-id-control.js
- │ │ └── rate-limiter.js
- │ ├── routes
- │ │ ├── index.js
- │ │ └── user.js
- │ └── validators
- │ ├── index.js
- │ └── user.validator.js
- ├── app.js
- ├── config
- │ └── index.js
- ├── loaders
- │ ├── express.js
- │ ├── index.js
- │ └── mongoose.js
- ├── models
- │ ├── index.js
- │ ├── log.js
- │ ├── token.js
- │ └── user.js
- └── utils
- ├── helpers
- │ ├── error-helper.js
- │ ├── generate-random-code.js
- │ ├── ip-helper.js
- │ ├── jwt-token-helper.js
- │ └── local-text-helper.js
- ├── index.js
- ├── lang
- │ ├── en.json
- │ ├── get-text.json
- │ └── tr.json
- ├── logger.js
- └── send-code-to-email.js
-
-17 directories, 46 files
-```
-
+- Python
+- Flask
+- Node.Js
+- Data_Science
## Version
- 0.3.0
+ 0.3.1
## Contributing
Please refer to [Here](CONTRIBUTING.md) for contributing.
diff --git a/artec/__main__.py b/artec/__main__.py
index 23a2f7e..f36396c 100644
--- a/artec/__main__.py
+++ b/artec/__main__.py
@@ -1,9 +1,10 @@
from . import argparser as parser
from . import boiler
from . import logging, console_handler
+from .temp import *
__app_name__ = "Artec"
-__version__ = "0.3.0"
+__version__ = "0.3.1"
__desc__ = "Creates a configurable python project \
template in a given directory."
@@ -19,7 +20,6 @@ def main():
args = parser.main_args(__version__)
console_handler.setLevel(ERROR_LOGING[args.verbose])
-
builder = boiler.boiler_builder(
args.source, args.target, args.template, args.git
)
@@ -29,3 +29,4 @@ def main():
if __name__ == "__main__":
main()
+
diff --git a/artec/argparser.py b/artec/argparser.py
index b46bc19..52c5766 100644
--- a/artec/argparser.py
+++ b/artec/argparser.py
@@ -7,7 +7,7 @@
RawTextHelpFormatter,
_VersionAction,
)
-from .templates import templates
+from .temp import *
import sys
@@ -15,10 +15,7 @@ class list_templates(_VersionAction):
def __call__(self, parser: ArgumentParser, *args, **kwargs) -> None:
formatter = parser._get_formatter()
formatter.add_text(
- "".join(
- "Available templates\n\n",
- "\n".join([f"> {key.title()}\t" for key in templates.keys()]),
- )
+ list_available_templates()
)
parser._print_message(formatter.format_help(), sys.stdout)
parser.exit()
@@ -43,6 +40,7 @@ def __init__(self, appVersion):
def setup(self):
group = self.add_mutually_exclusive_group()
+
group.add_argument(
"-s",
"--source-file",
@@ -60,13 +58,21 @@ def setup(self):
required=False,
)
+
self.add_argument(
"-o",
"--output-directory",
dest="target",
help="Target output path where the structure will be created",
type=str,
- required=True,
+ )
+
+ self.add_argument(
+ "-i",
+ "--interactuve",
+ dest="interactive",
+ help="Runs artec in interactive mode.",
+ action="store_true",
)
self.add_argument(
@@ -107,7 +113,15 @@ def setup(self):
def main_args(appVersion) -> Namespace:
parser = Parser(appVersion)
parser.setup()
- return parser.parse_args()
+ args = parser.parse_args()
+
+ if args.interactive:
+ print("Running Artec in interactive mode ....")
+ else:
+ if not args.target:
+ parser.error("The '-o' argument is required when not in interactive mode.")
+
+ return args
if __name__ == "__main__":
diff --git a/artec/boiler.py b/artec/boiler.py
index 78e61ad..74aeda8 100644
--- a/artec/boiler.py
+++ b/artec/boiler.py
@@ -6,10 +6,11 @@
import os
from pathlib import Path
from . import exceptions as ex
-from . import templates as temps
+from .temp import *
from . import repo
from . import logger
+
class boiler_builder:
def __init__(
self,
@@ -29,13 +30,14 @@ def __init__(
def _source_temp(self, template) -> list[dict[str, str]]:
try:
- if template in temps.templates:
- structure = temps.templates[template].format(self.target)
+ if template in templates:
+ structure = format_project_structure(templates[template], self.target)
+
else:
raise ex.InValidTemplate()
except ex.InValidTemplate:
- structure = temps.templates["python"].format(self.target)
+ structure = format_project_structure(templates["python"], self.target)
return structure
def _source(self, source) -> list[dict[str, str]]:
@@ -44,33 +46,30 @@ def _source(self, source) -> list[dict[str, str]]:
raise ex.NoSource()
if os.path.isfile(source) and source.endswith(".json"):
with open(source, "rt", encoding="utf-8") as file_data:
- structure = temps.static_list(json.load(file_data)).format(
+ structure = format_project_structure(json.load(file_data),
self.target
)
else:
raise ex.NotJsonFile()
except Exception:
- structure = temps.templates["python"].format(self.target)
+ structure = format_project_structure(templates["python"], self.target)
return structure
def build(self):
print("> Creating folder structure: {}\n".format(self.target))
- for entry in self.structure:
- for _type, name in entry.items():
- try:
- joined = Path(os.path.join(self.target, name))
- if "folder" in _type:
- self._make_folder(joined)
- elif "file" in _type:
- self._make_file(joined)
- else:
- raise ex.NotValidJson()
- print("Created: %s" % joined)
- except Exception:
- pass
+ for folder in self.structure['folders']:
+ folder_path = os.path.join(self.target, folder)
+ self._make_folder(folder_path)
+ print("Created: {}".format(folder_path))
+
+ for file_path in self.structure['files']:
+ file_path = os.path.join(self.target, file_path)
+ self._make_file(file_path)
+ print("Created: {}".format(file_path))
+
print()
if self.git:
@@ -83,7 +82,6 @@ def build(self):
def _make_file(self, path):
"""Create an empty file in a given directory"""
- path.parent.mkdir(parents=True, exist_ok=True)
open(path, "a").close()
def _make_folder(self, path):
diff --git a/artec/temp/__init__.py b/artec/temp/__init__.py
new file mode 100644
index 0000000..1cf3700
--- /dev/null
+++ b/artec/temp/__init__.py
@@ -0,0 +1,43 @@
+from os import listdir, path
+from .. import exceptions as ex
+from json import load
+
+DIR = path.dirname(path.abspath(__file__))
+
+
+def list_available_templates() -> str :
+ all_templates = "Available templates: \n\n"
+ all_templates += "\n".join(
+ [
+ f"> {key.title()}\t" for key in templates.keys()
+ ]
+ )
+ return all_templates
+
+def format_project_structure(template, project_name):
+ formatted_structure = {k: [] for k in template.keys()}
+ try:
+ for folder in template['folders']:
+ formatted_structure['folders'].append(folder.format(project_name))
+
+ for file_path in template['files']:
+ formatted_structure['files'].append(file_path.format(project_name))
+ except Exception :
+ raise ex.NotValidJson()
+
+ return formatted_structure
+
+def open_load(file_path):
+ with open(path.join(DIR, file_path), "rt") as file:
+ data = load(file)
+
+ return data
+
+
+
+templates = {
+ filename.removesuffix(".json"): open_load(path.join(DIR, filename))
+ for filename in listdir(DIR)
+ if filename.endswith(".json")
+}
+
diff --git a/artec/temp/data_science.json b/artec/temp/data_science.json
new file mode 100644
index 0000000..87c9349
--- /dev/null
+++ b/artec/temp/data_science.json
@@ -0,0 +1,38 @@
+{
+ "folders": [
+ "data",
+ "data/external",
+ "data/raw",
+ "data/processed",
+ "data/interim",
+ "docs",
+ "models",
+ "notebooks",
+ "refrences",
+ "reports",
+ "reports/figures",
+ "src",
+ "src/data",
+ "src/features",
+ "src/models",
+ "src/visualization"
+ ],
+ "files": [
+ "docs/Makefile",
+ "docs/commands.rst",
+ "docs/conf.py",
+ "docs/getting-started.rst",
+ "docs/index.rst",
+ "docs/make.bat",
+ "src/__init__.py",
+ ".env",
+ ".gitignore",
+ "README.md",
+ "LICENSE",
+ "Makefile",
+ "requirements.txt",
+ "setup.py",
+ "tox.ini",
+ "test_environment.py"
+ ]
+}
\ No newline at end of file
diff --git a/artec/temp/flask.json b/artec/temp/flask.json
new file mode 100644
index 0000000..2177c66
--- /dev/null
+++ b/artec/temp/flask.json
@@ -0,0 +1,34 @@
+{
+ "folders": [
+ "{}",
+ "{}/templates",
+ "{}/templates/auth",
+ "{}/blog",
+ "{}/static",
+ "test"
+ ],
+ "files": [
+ "{}/__init__.py",
+ "{}/db.py",
+ "{}/schema.py",
+ "{}/auth.py",
+ "{}/blog.py",
+ "{}/templates/base.html",
+ "{}/templates/auth/login.html",
+ "{}/templates/auth/register.html",
+ "{}/blog/create.html",
+ "{}/blog/index.html",
+ "{}/blog/update.html",
+ "{}/static/style.css",
+ "test/__init__.py",
+ "test/conftest.py",
+ "test/data.sql",
+ "test/test_db.py",
+ "test/test_auth.py",
+ "test/test_blog.py",
+ "README.md",
+ "LICENSE",
+ "setup.py",
+ "pyproject.toml"
+ ]
+}
diff --git a/artec/temp/nodejs.json b/artec/temp/nodejs.json
new file mode 100644
index 0000000..af21726
--- /dev/null
+++ b/artec/temp/nodejs.json
@@ -0,0 +1,69 @@
+{
+ "folders": [
+ "src",
+ "src/api",
+ "src/api/controllers",
+ "src/api/controllers/user",
+ "src/api/controllers/user/auth",
+ "src/api/controllers/user/edit",
+ "src/api/middlewares",
+ "src/api/middlewares/auth",
+ "src/api/routes",
+ "src/api/validators",
+ "src/config",
+ "src/loaders",
+ "src/models",
+ "src/utils",
+ "src/utils/helpers",
+ "src/utils/lang"
+ ],
+ "files": [
+ "src/api/controllers/user/auth/forgot-password.js",
+ "src/api/controllers/user/auth/login.js",
+ "src/api/controllers/user/auth/logout.js",
+ "src/api/controllers/user/auth/refresh-token.js",
+ "src/api/controllers/user/auth/register.js",
+ "src/api/controllers/user/auth/send-verification-code.js",
+ "src/api/controllers/user/auth/verify-email.js",
+ "src/api/controllers/user/edit/change-password.js",
+ "src/api/controllers/user/edit/edit-user.js",
+ "src/api/controllers/user/delete-user.js",
+ "src/api/controllers/user/get-user.js",
+ "src/api/controllers/user/index.js",
+ "src/api/middlewares/auth/check-auth.js",
+ "src/api/middlewares/auth/check-authority.js",
+ "src/api/middlewares/image-upload.js",
+ "src/api/middlewares/index.js",
+ "src/api/middlewares/object-id-control.js",
+ "src/api/middlewares/rate-limiter.js",
+ "src/api/routes/index.js",
+ "src/api/routes/user.js",
+ "src/api/validators/index.js",
+ "src/api/validators/user.validator.js",
+ "src/config/index.js",
+ "src/loaders/index.js",
+ "src/loaders/express.js",
+ "src/loaders/mongoose.js",
+ "src/models/index.js",
+ "src/models/log.js",
+ "src/models/token.js",
+ "src/models/user.js",
+ "src/utils/helpers/error-helper.js",
+ "src/utils/helpers/generate-random-code.js",
+ "src/utils/helpers/ip-helper.js",
+ "src/utils/helpers/jwt-token-helper.js",
+ "src/utils/helpers/local-text-helper.js",
+ "src/utils/lang/en.json",
+ "src/utils/lang/get-text.json",
+ "src/utils/lang/tr.json",
+ "src/utils/index.js",
+ "src/utils/logger.js",
+ "src/utils/send-code-to-email.js",
+ "src/app.js",
+ ".env.sample",
+ "README.md",
+ "LICENSE",
+ "package.json",
+ "package-lock.json"
+ ]
+}
diff --git a/artec/temp/python.json b/artec/temp/python.json
new file mode 100644
index 0000000..a36d2bc
--- /dev/null
+++ b/artec/temp/python.json
@@ -0,0 +1,14 @@
+{
+ "folders": [
+ "{}",
+ "test"
+ ],
+ "files": [
+ "{}/__init__.py",
+ "test/__init__.py",
+ "README.md",
+ "LICENSE",
+ "setup.py",
+ "pyproject.toml"
+ ]
+}
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index d7062da..ca1914d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ exclude = ["img*"]
[project]
name = "Artec"
-version = "0.3.0"
+version = "0.3.1"
authors = [
{ name="HushmKun", email="HushmKun@outlook.com" },
{ name="Link-", email="bsm.dgdy@gmail.com" },
diff --git a/test/resources/structure.json b/test/resources/structure.json
index 7569ac8..785dc1d 100644
--- a/test/resources/structure.json
+++ b/test/resources/structure.json
@@ -1,11 +1,14 @@
-[
- {"folder": "{}"},
- {"file": "{}/__init__.py"},
- {"folder": "test"},
- {"file": "test/__init__.py"},
- {"file": "README.md"},
- {"file": "LICENSE"},
- {"file": "setup.py"},
- {"file": "setup.cfg"},
- {"file": "pyproject.toml"}
-]
\ No newline at end of file
+{
+ "folders": [
+ "{}",
+ "test"
+ ],
+ "files": [
+ "{}/__init__.py",
+ "test/__init__.py",
+ "README.md",
+ "LICENSE",
+ "setup.py",
+ "pyproject.toml"
+ ]
+}
diff --git a/test/test_boiler.py b/test/test_boiler.py
index 8e9cfd6..9185872 100644
--- a/test/test_boiler.py
+++ b/test/test_boiler.py
@@ -3,7 +3,8 @@
import git
from pathlib import Path
from artec.boiler import boiler_builder
-from artec.templates import static_list, templates
+
+from artec.temp import *
VAILD_JSON = Path("./test/resources/structure.json")
INVAILD_JSON = Path("./test/resources/structure.txt")
@@ -15,19 +16,19 @@ def test_init(self):
source="structure.json", target="target"
)
self.assertEqual(builder.target, "target")
- self.assertIsInstance(builder.structure, list)
+ self.assertIsInstance(builder.structure, dict)
def test_source_temp(self):
builder = boiler_builder(
template="python", target="target"
)
self.assertEqual(
- builder.structure, templates["python"].format("target")
+ builder.structure, format_project_structure(templates["python"], "target")
)
def test_source(self):
with open(VAILD_JSON, "rt", encoding="utf-8") as file_data:
- structure = static_list(json.load(file_data)).format("target")
+ structure = format_project_structure(json.load(file_data),"target")
builder = boiler_builder(
source=VAILD_JSON, target="target"
)
@@ -56,19 +57,19 @@ def test_exception_handling(self):
source=INVAILD_JSON, target="target"
)
self.assertEqual(
- builder.structure, templates["python"].format("target")
+ builder.structure, format_project_structure(templates["python"],"target")
)
builder = boiler_builder(
template="invalid", target="target"
)
self.assertEqual(
- builder.structure, templates["python"].format("target")
+ builder.structure, format_project_structure(templates["python"],"target")
)
builder = boiler_builder(target="target")
self.assertEqual(
- builder.structure, templates["python"].format("target")
+ builder.structure, format_project_structure(templates["python"],"target")
)