diff --git a/.env b/.env new file mode 100644 index 0000000..f55c67a --- /dev/null +++ b/.env @@ -0,0 +1 @@ +FENV_VERSION = "0.0.11.6" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 931c448..d910f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ __pycache__/ .idea test site -build \ No newline at end of file +build +test/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 20387fa..0d6e5dd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1 @@ -{ - "docwriter.style": "Google", - "python.formatting.provider": "black", - "editor.formatOnSave": false -} \ No newline at end of file +{"python.formatting.provider": "black","python.pythonPath": "Fenv-Module","editor.formatOnSave": true,} \ No newline at end of file diff --git a/Fenv.egg-info/PKG-INFO b/Fenv.egg-info/PKG-INFO index 964f792..34c0d08 100644 --- a/Fenv.egg-info/PKG-INFO +++ b/Fenv.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: Fenv -Version: 0.0.11.4 +Version: 0.0.11.5 Summary: Generate a folder, establish a virtual environment with a single command. Author: wk18k (watchakorn-18k) Author-email: @@ -30,13 +30,17 @@ Fenv is a simple and efficient tool to help you manage your virtual environments - Packages can be installed and uninstalled and added to files. requirements.txt at the same time ## Docs + https://watchakorn-18k.github.io/Fenv/ ## Installer + ``` pip install fenv ``` + or + ``` pip install --upgrade fenv ``` @@ -47,7 +51,6 @@ pip install --upgrade fenv fenv new ``` - ## Command ```cmd @@ -59,7 +62,7 @@ Usage: Commands: new Create a new project - install Install packages + install Install packages and install requirements.txt uninstall Uninstall packages update Update packages to file requirements.txt onlyenv Create only virtualenv and no create base file @@ -87,20 +90,36 @@ Fenv is a powerful tool for managing virtual environments and creating basic Pyt ## Changelog +### 0.0.11.5 + +- [x] Added Tree path in md after generating projects , can you try command `fenv update` ![](https://i.imgur.com/vDz2Gs0.gif) +- [x] Added create file .gitignore +- [x] Edit readme.md small changes +- [x] Fix if an `env` folder does not exist, the modified `fenv install ` command will prompt you to confirm whether you would like to create a new `env`. If you choose not to create a new `env`, the installation will proceed using `python main` ![](https://i.imgur.com/M0shh8x.gif) +- [x] Added command `fenv install` alone will install file requirements.txt in directory current ![](https://i.imgur.com/cgApbCa.gif) +- [x] Added after use `fenv onlyenv` created settings then activate env one time ![](https://i.imgur.com/mwEUSrg.gif) + ### 0.0.11.4 -- [x] fix bugs small + +- [x] Fix bugs small + ### 0.0.11.3 -- [x] fix bugs settings in .vscode -- [x] fix bugs line 609 and 624 + +- [x] Fix bugs settings in .vscode +- [x] Fix bugs line 609 and 624 + ### 0.0.11.2 -- [x] fix bugs small + +- [x] Fix bugs small + ### 0.0.11.1 -- [x] change new pattern command + +- [x] Change new pattern command `-onlyenv` to `onlyenv` ### 0.0.10 -- [x] add option -onlyenv for create only virtualenv without base file all -- [X] add command install for install package and add module to file requirements.txt +- [x] Add option `-onlyenv` for create only virtualenv without base file all +- [x] Add command install for install package and add module to file requirements.txt ### 0.0.9 diff --git a/build/lib/fenv/fenv.py b/build/lib/fenv/fenv.py index 54f50f3..3c6f0aa 100644 --- a/build/lib/fenv/fenv.py +++ b/build/lib/fenv/fenv.py @@ -3,53 +3,149 @@ import platform import re import random +import fnmatch class bcolors: """It's a class that contains a bunch of variables that are strings of ANSI escape codes. Example: ``` - bcolors.HEADER - bcolors.OKBLUE - bcolors.OKGREEN - bcolors.WARNING - bcolors.FAIL - bcolors.ENDC + Colors.HEADER + Colors.OKBLUE + Colors.OKGREEN + Colors.WARNING + Colors.FAIL + Colors.ENDC ``` Return: None """ - HEADER = "\033[95m" - OKBLUE = "\033[94m" - OKGREEN = "\033[92m" - WARNING = "\033[93m" - FAIL = "\033[91m" - ENDC = "\033[0m" - def __init__(self): - self.HEADER = "" - self.OKBLUE = "" - self.OKGREEN = "" - self.WARNING = "" - self.FAIL = "" - self.ENDC = "" +class Colors: + ESCAPE_SEQ = { + "HEADER": "\033[95m", + "OKBLUE": "\033[94m", + "OKGREEN": "\033[92m", + "WARNING": "\033[93m", + "FAIL": "\033[91m", + "ENDC": "\033[0m", + "BOLD": "\033[1m", + "UNDERLINE": "\033[4m", + } + + TEXT_COLORS = { + "BLACK": "\033[30m", + "RED": "\033[31m", + "GREEN": "\033[32m", + "YELLOW": "\033[33m", + "BLUE": "\033[34m", + "MAGENTA": "\033[35m", + "CYAN": "\033[36m", + "WHITE": "\033[37m", + } + + LIGHT_COLORS = { + "LIGHTBLACK_EX": "\033[90m", + "LIGHTRED_EX": "\033[91m", + "LIGHTGREEN_EX": "\033[92m", + "LIGHTYELLOW_EX": "\033[93m", + "LIGHTBLUE_EX": "\033[94m", + "LIGHTMAGENTA_EX": "\033[95m", + "LIGHTCYAN_EX": "\033[96m", + "LIGHTWHITE_EX": "\033[97m", + } + + COLOR256 = { + "PURPLE": "\033[38;5;129m", + "ORANGE": "\033[38;5;202m", + "BROWN": "\033[38;5;130m", + "OLIVE": "\033[38;5;142m", + "GOLD": "\033[38;5;214m", + "SILVER": "\033[38;5;188m", + "MAROON": "\033[38;5;52m", + "NAVY": "\033[38;5;21m", + "TEAL": "\033[38;5;29m", + "LIME": "\033[38;5;118m", + "AQUA": "\033[38;5;45m", + "FUSCHIA": "\033[38;5;161m", + "PURPLE2": "\033[38;5;98m", + "PLUM": "\033[38;5;88m", + "INDIGO": "\033[38;5;54m", + "TURQUOISE": "\033[38;5;80m", + "STEEL_BLUE": "\033[38;5;67m", + "ROSE": "\033[38;5;210m", + "HOT_PINK": "\033[38;5;200m", + "SALMON": "\033[38;5;173m", + "CORAL": "\033[38;5;203m", + "BEIGE": "\033[38;5;230m", + "KHAKI": "\033[38;5;143m", + "FOREST_GREEN": "\033[38;5;34m", + "OLIVE_GREEN": "\033[38;5;58m", + "LAVENDER": "\033[38;5;183m", + "ORCHID": "\033[38;5;170m", + "LILAC": "\033[38;5;134m", + "SKY_BLUE": "\033[38;5;117m", + "BABY_BLUE": "\033[38;5;152m", + "POWDER_BLUE": "\033[38;5;165m", + "SEA_GREEN": "\033[38;5;27m", + "PALE_GREEN": "\033[38;5;120m", + "SPRING_GREEN": "\033[38;5;48m", + "MINT_GREEN": "\033[38;5;121m", + "GRAY_BLUE": "\033[38;5;103m", + "BLUE_GRAY": "\033[38;5;104m", + } + + def __getattr__(self, name): + if name in self.ESCAPE_SEQ: + return self.ESCAPE_SEQ[name] + elif name in self.TEXT_COLORS: + return self.TEXT_COLORS[name] + elif name in self.LIGHT_COLORS: + return self.LIGHT_COLORS[name] + elif name in self.COLOR256: + return self.COLOR256[name] + else: + raise AttributeError +Colors = Colors() # Defining a variable called notice. notice = ( - bcolors.OKBLUE + Colors.OKBLUE + "[" - + bcolors.ENDC - + bcolors.OKGREEN + + Colors.ENDC + + Colors.OKGREEN + "notice" - + bcolors.OKBLUE + + Colors.OKBLUE + "]" - + bcolors.ENDC + + Colors.ENDC + " " ) +def env_directory(): + """It's a function that checks if the environment directory exists. + Return: + [] : empyt list + """ + folder_name = "env*" + return ( + fnmatch.filter(os.listdir("."), folder_name) + if fnmatch.filter(os.listdir("."), folder_name) == [] + else str(fnmatch.filter(os.listdir("."), folder_name)[0]) + ) + + +def root_directory(): + """It's a function that checks if the root directory exists. + + Return: + str : root directory + """ + return os.path.basename(os.path.abspath(".")) + + def create_dir_file(path, text): """It creates a directory if it doesn't exist, and then creates a file in that directory with the given text @@ -110,35 +206,35 @@ def create_folder(folder_name): def create_setting_vscode(env_path): """ - It creates a file called settings.json in a directory called .vscode. - - The file contains a JSON object with two keys: - + It creates a file called settings.json in a directory called .vscode. + + The file contains a JSON object with two keys: + - python.formatting.provider - python.pythonPath - - The value of the first key is the string "black". - - The value of the second key is the path to the virtual environment. - - The function also prints a message to the console. - - The message is a string that contains the value of the global variable notice. - - The message also contains the string "Successfully created the .vscode/settings.json". - - The function ends with the keyword def. - - The function is called create_setting_vscode. - - The function takes one argument. - - The argument is called env_path. - - The function begins with the keyword def. - + + The value of the first key is the string "black". + + The value of the second key is the path to the virtual environment. + + The function also prints a message to the console. + + The message is a string that contains the value of the global variable notice. + + The message also contains the string "Successfully created the .vscode/settings.json". + + The function ends with the keyword def. + + The function is called create_setting_vscode. + + The function takes one argument. + + The argument is called env_path. + + The function begins with the keyword def. + The function ends with the - + Args: env_path (str): The path to the virtual environment Example: @@ -154,12 +250,13 @@ def create_setting_vscode(env_path): print(notice + f"Successfully created the .vscode/settings.json") -def create_file_base(name): +def create_file_base(name, state): """ It creates a file called main.py and writes a function called main() inside of it Args: name (str): The name of the project + state (str): The state of the project Example: ```py create_file_base("project_name") @@ -187,6 +284,28 @@ def main(): os.chmod(file_path, 0o777) print(notice + f'Successfully created the file "{file_path}"') + def generate_tree(startpath): + output = "" + for root, dirs, files in os.walk(startpath): + level = root.replace(startpath, "").count(os.sep) + if level == 0: + indent = " " * (level + 1) + "│ " + subindent = " " * (level + 2) + for d in dirs: + dir_path = os.path.join(root, d) + output += f"{subindent}{'└──'}{d}/\n" + if d == ".vscode": + output += f"{subindent}{subindent}{'└──'}settings.json\n" + if d == env_directory(): + for i in ["Lib/", "Scripts", ".gitignore", "pyvenv.cfg"]: + output += f"{subindent}{subindent}{'└──'} {i}\n" + + for f in files: + file_path = os.path.join(root, f) + output += f"{subindent}{'└──'}{f}\n" + print(os.getcwd()) + return output + def create_file_readme_md(): """ It creates a file called readme.md and writes the markdown text to it @@ -194,7 +313,6 @@ def create_file_readme_md(): markdown_path = "readme.md" markdown = """ # {} - A brief and descriptive title for your project. ## Description @@ -204,13 +322,36 @@ def create_file_readme_md(): ## Getting Started ``` -pip install -r requirements.txt +git clone https://github.com//{}.git + +cd {} + +``` + +## Installation + +``` +# create virtualenv auto name +fenv onlyenv + +# install package in requirements.txt +fenv install + ``` ## Usage Instructions on how to use the project, including any usage examples and screenshots. +## Tree + +```bash +. +└── {}/ +{} +``` + + ## Contributing If you would like to contribute to the project, include a section on how to do so, including any guidelines and best practices. @@ -220,8 +361,10 @@ def create_file_readme_md(): Include information about the license used for the project, such as the name of the license (e.g. MIT, Apache 2.0, etc.) and a link to the license text. """ - with open(markdown_path, "w") as f: - f.write(markdown.format(name)) + with open(markdown_path, "w", encoding="utf-8") as f: + f.write( + markdown.format(name, name, name, env_directory(), generate_tree(".")) + ) os.chmod(markdown_path, 0o777) print(notice + f'Successfully created the file "{markdown_path}"') @@ -236,12 +379,65 @@ def create_file_freeze(): os.chmod("requirements.txt", 0o777) print(notice + f'Successfully created the file "requirements.txt"') - create_file_main_py() - create_file_readme_md() - create_file_freeze() + def create_file_gitignore(): + """ + It creates a file called .gitignore and writes the string "*.pyc" to it + """ + with open(".gitignore", "w") as f: + f.write(f"*.pyc\n/{env_directory()}") + os.chmod(".gitignore", 0o777) + print(notice + f'Successfully created the file ".gitignore"') + def update_file_readme_md(): + """ + It update a file called readme.md and writes the markdown text to it + """ + markdown_path = "readme.md" + with open(markdown_path, "r", encoding="utf-8") as f: + data = f.readlines() + + for i, v in enumerate(data): + if "" in v: + first = i + + if "" in v: + last = i + + data = data[: first + 1] + data[last:] + + for i, v in enumerate(data): + if "" in v: + data[ + i + ] = """ + +```bash +. +└── {}/ +{} +``` +""".format( + env_directory(), generate_tree(".") + ) + with open(markdown_path, "w", encoding="utf-8") as f: + f.writelines(data) + os.chmod(markdown_path, 0o777) -"" + """ + create_file_base main call function + """ + if state == "create": + create_file_main_py() + create_file_freeze() + create_file_gitignore() + create_file_readme_md() + update_file_readme_md() + elif state == "update": + update_file_readme_md() + + """ + end of create_file_base function + """ def run_install_module_base(env): @@ -279,7 +475,7 @@ def create_project_all(name): print(notice + "Creating...") create_virtualenv(name) create_setting_vscode(name) - create_file_base(name) + create_file_base(name, "create") run_install_module_base(name) @@ -338,7 +534,7 @@ def cmd_install_package(args): try: if platform.system() == "Windows": os.system( - f".\{name_env()}\Scripts\python.exe -m pip install {args.install}" + f".\{env_directory()}\Scripts\python.exe -m pip install {args.install}" ) print(notice + f"Successfully installed module {args.install}") except TimeoutError: @@ -359,8 +555,13 @@ def add_module_to_txt(args): None """ - os.system(f"pip freeze > requirements.txt") - print(notice + f'Successfully module {args.install} added to "requirements.txt"') + if env_directory(): + os.system( + f".\{env_directory()}\Scripts\python.exe -m pip freeze > requirements.txt" + ) + print( + notice + f'Successfully module {args.install} added to "requirements.txt"' + ) def find_dir_env() -> str: @@ -378,7 +579,7 @@ def find_dir_env() -> str: def install_package(args): """ It takes a list of packages, and installs them using the `pip` command - + Args: args (str): The arguments passed to the command Example: @@ -409,7 +610,7 @@ def cmd_uninstall_package(args): try: if platform.system() == "Windows": os.system( - f".\{name_env()}\Scripts\python.exe -m pip uninstall {args.uninstall}" + f".\{env_directory()}\Scripts\python.exe -m pip uninstall {args.uninstall}" ) print(notice + f"Successfully uninstalled module {args.uninstall}") except TimeoutError: @@ -419,7 +620,7 @@ def cmd_uninstall_package(args): def remove_module_exit_txt(args): """ It removes the module from the requirements.txt file - + Args: args (str): This is the argument that is passed to the function. Example: @@ -443,7 +644,7 @@ def remove_module_exit_txt(args): def uninstall_package(args): """ It will uninstall the package and remove the module exit text file - + Args: args (str): The arguments passed to the script. Example: @@ -474,7 +675,11 @@ def setup_parse(): "new", type=str, help="The name of the project", nargs="?", default=None ) - install_cmd = subparsers.add_parser("install", help="Install packages") + install_cmd = subparsers.add_parser( + "install", + help="Install the package and install the package via requirements.txt", + usage=f"{Colors.NAVY}fenv install {Colors.NAVY}{Colors.ENDC} or {Colors.HOT_PINK}fenv install {Colors.ENDC}", + ) install_cmd.add_argument( "install", type=str, @@ -483,7 +688,11 @@ def setup_parse(): default=None, ) - uninstall_cmd = subparsers.add_parser("uninstall", help="Uninstall packages") + uninstall_cmd = subparsers.add_parser( + "uninstall", + help="Uninstall packages", + usage=f"{Colors.HOT_PINK}fenv uninstall {Colors.ENDC}", + ) uninstall_cmd.add_argument( "uninstall", type=str, @@ -493,11 +702,15 @@ def setup_parse(): ) update_cmd = subparsers.add_parser( - "update", help="Update packages to file requirements.txt" + "update", + help="Package to file requirements.txt update furthermore, update the readme.md file's tree path.", + usage=f"{Colors.HOT_PINK}fenv update{Colors.ENDC}", ) onlyenv_cmd = subparsers.add_parser( - "onlyenv", help="Create only virtualenv and no create base file" + "onlyenv", + help=f"Create only virtualenv and no create base file", + usage=f"{Colors.HOT_PINK}fenv onlyenv{Colors.ENDC}", ) # clean_cmd = subparsers.add_parser( @@ -508,6 +721,9 @@ def setup_parse(): general_group.add_argument( "-h", "--help", action="help", help="Show this help message and exit" ) + general_group.add_argument( + "-v", "--version", action="store_true", help="check version fenv" + ) args = parser.parse_args() @@ -517,7 +733,7 @@ def setup_parse(): def run_cmd_new(args): """ It creates a new project folder and then creates a virtual environment inside that folder - + Args: args (str): The arguments passed to the command. Example: @@ -534,11 +750,11 @@ def run_cmd_new(args): print( "Maybe you forgot to enter the name of the folder? for example" + " `" - + bcolors.OKGREEN + + Colors.MINTGREEN + "fenv new" - + bcolors.OKBLUE + + Colors.NAVY + " " - + bcolors.ENDC, + + Colors.ENDC, "`", ) @@ -546,7 +762,7 @@ def run_cmd_new(args): def run_cmd_install(args): """ It tries to install a package, if it fails, it prints a message - + Args: args (str): The arguments passed to the command. Example: @@ -558,23 +774,108 @@ def run_cmd_install(args): """ try: - print("Installing...") - install_package(args) + if env_directory(): + install_package(args) + else: + while True: + response = input( + "We couldn't find the fenv virtual environment. Would you like to set up a new one? (y/n): " + ) + if ( + response.lower() == "y" + or response.lower() == "yes" + or response.lower() == "" + ): + run_cmd_onlyenv() + folder_name = "env*" + folder_name_env = str( + fnmatch.filter(os.listdir("."), folder_name)[0] + ) + install_package(args) + break + elif response.lower() == "n": + install_package(args) + break except AttributeError as err: print( - bcolors.OKGREEN + Colors.MINTGREEN + "An error was encountered, it could not be installed." - + bcolors.ENDC + + Colors.ENDC + ) + + +def install_package_all(): + """ + install all packages in requirements.txt file using pip install -r requirements.txt + """ + + folder_name = "env*" + folder_name_env = ( + fnmatch.filter(os.listdir("."), folder_name) + if fnmatch.filter(os.listdir("."), folder_name) == [] + else str(fnmatch.filter(os.listdir("."), folder_name)[0]) + ) + requirements_file = "requirements.txt" + + def install_package_follow_env(folder_name_env): + if platform.system() == "Windows": + os.system( + f".\{folder_name_env}\Scripts\python.exe -m pip install -r requirements.txt" + ) + + def run_install_main(folder_name_env): + if folder_name_env: + print( + f"Found directory `{Colors.MINTGREEN}{folder_name_env}{Colors.ENDC}`" + ) + print( + f"Installing modules with `{Colors.MINTGREEN}{folder_name_env}{Colors.ENDC}`" + ) + install_package_follow_env(folder_name_env) + print(notice + f'Successfully installed module from "requirements.txt"') + else: + while True: + response = input( + "We couldn't find the fenv virtual environment. Would you like to set up a new one? (y/n): " + ) + if ( + response.lower() == "y" + or response.lower() == "yes" + or response.lower() == "" + ): + run_cmd_onlyenv() + folder_name = "env*" + folder_name_env = str( + fnmatch.filter(os.listdir("."), folder_name)[0] + ) + print( + f"Installing modules with `{Colors.MINTGREEN}{folder_name_env}{Colors.ENDC}`" + ) + install_package_follow_env(folder_name_env) + print( + notice + + f'Successfully installed module from "requirements.txt"' + ) + break + elif response.lower() == "n": + os.system(f"pip install -r requirements.txt") + break + + if requirements_file in os.listdir("."): + run_install_main(folder_name_env) + else: + print( + f"Maybe you forgot to put the name of the package to ininstall? for example `{Colors.MINTGREEN}fenv ininstall{Colors.OKBLUE} {Colors.ENDC}` \nOr you can use `{Colors.MINTGREEN}fenv ininstall{Colors.ENDC}` alone. But there must be {Colors.FAIL}{requirements_file}{Colors.ENDC} in the current directory" ) def run_cmd_uninstall(args): """ "A function that is called when the user runs the command "uninstall"." - + The first line of the function is a docstring. It's a string that describes what the function does. It's a good idea to include a docstring for every function you write - + Args: args (str): The arguments passed to the command Example: @@ -586,7 +887,7 @@ def run_cmd_uninstall(args): """ try: print(notice + "Uninstalling...") - # uninstall_package(args) + uninstall_package(args) except AttributeError as err: print(err, "An error was encountered, it could not be uninstalled.") @@ -599,7 +900,6 @@ def run_cmd_onlyenv(): None """ - def create_name_env_auto() -> str: """ > It creates a random name for the environment @@ -634,7 +934,7 @@ def is_english_only(s): def create_virtualenv(virtual_env_name): """ It creates a virtual environment with the name you pass to it - + Args: virtual_env_name (str): The name of the virtual environment you want to create. @@ -654,9 +954,9 @@ def create_virtualenv(virtual_env_name): print(notice + f'Successfully created the virtualenv "{virtual_env_name}"') _name_env = create_name_env() - print(f"your env name is `{bcolors.OKGREEN}{_name_env}{bcolors.ENDC}`") + print(f"your env name is `{Colors.MINTGREEN}{_name_env}{Colors.ENDC}`") create_virtualenv(_name_env) - dir_name_only = os.path.basename(os.getcwd()) # get name dir main + dir_name_only = os.path.basename(os.getcwd()) # get name dir main create_setting_vscode(dir_name_only) @@ -687,35 +987,29 @@ def check_command(args): if args.__dict__["command"] == "new": run_cmd_new(args) elif args.__dict__["command"] == "install": - run_cmd_install(args) if args.install != None else print( - "Maybe you forgot to put the name of the package to install? for example" - + " `" - + bcolors.OKGREEN - + "fenv install" - + bcolors.OKBLUE - + " " - + bcolors.ENDC - + "`" - ) + run_cmd_install(args) if args.install != None else install_package_all() + elif args.__dict__["command"] == "uninstall": run_cmd_uninstall(args) if args.uninstall != None else print( "Maybe you forgot to put the name of the package to uninstall? for example" + " `" - + bcolors.OKGREEN + + Colors.MINTGREEN + "fenv uninstall" - + bcolors.OKBLUE + + Colors.OKBLUE + " " - + bcolors.ENDC + + Colors.ENDC + "`" ) elif args.__dict__["command"] == "update": + create_file_base(root_directory(), "update") + print(notice + "Updated tree path to readme.md") os.system("pip freeze > requirements.txt") print(notice + "Updated module all to requirements.txt") elif args.__dict__["command"] == "onlyenv": run_cmd_onlyenv() - elif args.__dict__["command"] == "clean": - run_cmd_clean() + # elif args.__dict__["command"] == "clean": + # run_cmd_clean() def main(): @@ -725,10 +1019,21 @@ def main(): None """ args = setup_parse() - version: str = "v0.0.11" - print(f"⏩ fenv {version}") if args.__dict__["command"] == None else None + version: str = "v0.0.11.5" + print( + f"⏩ {Colors.LIGHTMAGENTA_EX}Hello,Fenv {Colors.POWDER_BLUE}[{Colors.MINT_GREEN}{version}{Colors.POWDER_BLUE}]{Colors.ENDC}🫡\n".center( + 40, "-" + ) + ) if args.__dict__["command"] == None else None check_command(args) + # Colors.HEADER + # Colors.OKBLUE + # Colors.OKGREEN + # Colors.WARNING + # Colors.FAIL + # Colors.ENDC + # It's a way to make sure that the code in the `main` function is only run when the script is run. # if __name__ == "__main__": diff --git a/dist/Fenv-0.0.11.5-py3-none-any.whl b/dist/Fenv-0.0.11.5-py3-none-any.whl new file mode 100644 index 0000000..d162997 Binary files /dev/null and b/dist/Fenv-0.0.11.5-py3-none-any.whl differ diff --git a/dist/Fenv-0.0.11.5.tar.gz b/dist/Fenv-0.0.11.5.tar.gz new file mode 100644 index 0000000..d9e9a7a Binary files /dev/null and b/dist/Fenv-0.0.11.5.tar.gz differ diff --git a/docs/how-to-guides.md b/docs/how-to-guides.md index ec2febf..051f9ca 100644 --- a/docs/how-to-guides.md +++ b/docs/how-to-guides.md @@ -36,6 +36,12 @@ source env/bin/activate ## Install packages +``` +fenv install +``` + +One command can be used to install packages from requirements.txt, and if Fenv's virtual environment does not exist, it will prompt the user to create it. However, an error message will be displayed if the requirements.txt file cannot be located. + ``` fenv install ``` @@ -64,4 +70,4 @@ Update all packages to a file. requirements.txt fenv onlyenv ``` -Create a virtualenv with a custom name or an optional 2 autoname, then create a file. settings.json for vscode does not generate additional base files \ No newline at end of file +Create a virtualenv with a custom name or an optional 2 autoname, then create a file. settings.json for vscode does not generate additional base files diff --git a/docs/index.md b/docs/index.md index b0733b5..1b8a94b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,4 @@ - - -![versions](https://img.shields.io/pypi/pyversions/pybadges.svg) ![](https://img.shields.io/badge/-version%200.11-blue) +![versions](https://img.shields.io/pypi/pyversions/pybadges.svg) ![](https://img.shields.io/badge/-version%200.11.6-blue) # Fenv @@ -18,46 +16,62 @@ Fenv is a simple and efficient tool to help you manage your virtual environments - Packages can be installed and uninstalled and added to files. `requirements.txt` at the same time ## Installer + ``` pip install fenv ``` + or + ``` pip install --upgrade fenv ``` +## PyPi + +``` +https://pypi.org/project/Fenv/ +``` + ## Command ```cmd -$ fenv -h +usage: fenv [-h] [-v] ... Usage: - fenv [options] + fenv Commands: - new Create a new project - install Install packages - uninstall Uninstall packages - update Update packages to file requirements.txt - onlyenv Create only virtualenv and no create base file + new Create a new project + install Install the package and install the + package via requirements.txt + uninstall Uninstall packages + update Package to file requirements.txt update + furthermore, update the readme.md file's + tree path. + onlyenv Create only virtualenv and no create + base file General Options: - -h, --help Show this help message and exit + -h, --help Show this help message and exit + -v, --version check version fenv ``` ## Layout - |_ .vscode/ - | |_ settings.json - | - |_ env_name/ - | |_ Lib - | |_ Scripts - | |_ .gitignore - | |_ pyvenv - | - |_ main.py - |_ readme.md - |_ requirements.txt +``` +└── test/ + └──.vscode/ + └──settings.json + └──env_test/ + └── Lib/ + └── Scripts + └── .gitignore + └── pyvenv.cfg + └──.gitignore + └──main.py + └──readme.md + └──requirements.txt +``` diff --git a/docs/tutorials.md b/docs/tutorials.md index 62f8776..a935d11 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -3,3 +3,27 @@

Create a new project and create virtualenv with base file such `settings.json` on vscode and `main.py` + +## `fenv install` + +

+ +Install all modules in requirements.txt is similar to `npm install`. + +## `fenv install ` + +

+ +Install the modules you want to install. After the installation is complete add the module name to the file. automatic requirements.txt + +## `fenv uninstall ` + +

+ +Uninstall the modules you want to uninstall. After the uninstallation is complete add the module name to the file. automatic requirements.txt + +## `fenv onlyenv` + +

+ +Create a virtualenv with settings to connect the interpreter to vscode and format the code with black. diff --git a/fenv/__init__.py b/fenv/__init__.py index a7a10da..6b52aac 100644 --- a/fenv/__init__.py +++ b/fenv/__init__.py @@ -1,3 +1,5 @@ +from . import * + # fenv/__init__.py """Do math with your own functions. diff --git a/fenv/__pycache__/__init__.cpython-310.pyc b/fenv/__pycache__/__init__.cpython-310.pyc index be80edf..1930cfd 100644 Binary files a/fenv/__pycache__/__init__.cpython-310.pyc and b/fenv/__pycache__/__init__.cpython-310.pyc differ diff --git a/fenv/__pycache__/fenv.cpython-310.pyc b/fenv/__pycache__/fenv.cpython-310.pyc index 3bd6436..3ad4236 100644 Binary files a/fenv/__pycache__/fenv.cpython-310.pyc and b/fenv/__pycache__/fenv.cpython-310.pyc differ diff --git a/fenv/assets/__init__.py b/fenv/assets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fenv/assets/commands.py b/fenv/assets/commands.py new file mode 100644 index 0000000..ddc905c --- /dev/null +++ b/fenv/assets/commands.py @@ -0,0 +1,16 @@ +""" Code module for generating content files """ + + +class Commands: + def __init__(self, **kwargs) -> None: + self.kwargs = kwargs + + def get_main_py(self): + return """ +def main(): + pass + + +if __name__ == "__main__": + main() + """ diff --git a/fenv/create_file_base.py b/fenv/create_file_base.py new file mode 100644 index 0000000..3585d62 --- /dev/null +++ b/fenv/create_file_base.py @@ -0,0 +1,193 @@ +""" Module creates a file called main.py and writes a function called main() inside of it""" +import os +from fenv.customizes.colors import Colors +from fenv.assets.commands import Commands +from fenv.env_all import EnvAll + +Colors = Colors() +Commands = Commands() +notice = Colors.notice() +env_name = EnvAll() + + +class CreateFileBase: + def __init__(self, name, stat): + self.name = name + self.stat = stat + + def create_file_main_py(): + """ + Create a file main.py and write a function called main() inside of it + """ + file_path = "main.py" + with open(file_path, "w") as f: + f.write(Commands.get_main_py()) + os.chmod(file_path, 0o777) + print(notice + f'Successfully created the file "{file_path}"') + + def generate_tree(startpath): + output = "" + for root, dirs, files in os.walk(startpath): + level = root.replace(startpath, "").count(os.sep) + if level == 0: + indent = " " * (level + 1) + "│ " + subindent = " " * (level + 2) + for d in dirs: + dir_path = os.path.join(root, d) + output += f"{subindent}{'└──'}{d}/\n" + if d == ".vscode": + output += f"{subindent}{subindent}{'└──'}settings.json\n" + if d == env_name.get_env_name(): + for i in ["Lib/", "Scripts", ".gitignore", "pyvenv.cfg"]: + output += f"{subindent}{subindent}{'└──'} {i}\n" + + for f in files: + file_path = os.path.join(root, f) + output += f"{subindent}{'└──'}{f}\n" + print(os.getcwd()) + return output + + +def create_file_base(name, state): + """ + Args: + name (str): The name of the project + state (str): The state of the project + Example: + ```py + create_file_base("project_name") + ``` + Return: + None + """ + + def create_file_readme_md(): + """ + It creates a file called readme.md and writes the markdown text to it + """ + markdown_path = "readme.md" + markdown = """ +# {} +A brief and descriptive title for your project. + +## Description + +A detailed description of the project, including its purpose, features, and any other relevant information. + +## Getting Started + +``` +git clone https://github.com//{}.git + +cd {} + +``` + +## Installation + +``` +# create virtualenv auto name +fenv onlyenv + +# install package in requirements.txt +fenv install + +``` + +## Usage + +Instructions on how to use the project, including any usage examples and screenshots. + +## Tree + +```bash +. +└── {}/ +{} +``` + + +## Contributing + +If you would like to contribute to the project, include a section on how to do so, including any guidelines and best practices. + +## License + +Include information about the license used for the project, such as the name of the license (e.g. MIT, Apache 2.0, etc.) and a link to the license text. + +""" + with open(markdown_path, "w", encoding="utf-8") as f: + f.write(markdown.format(name, name, name, name, generate_tree("."))) + os.chmod(markdown_path, 0o777) + print(notice + f'Successfully created the file "{markdown_path}"') + + def create_file_freeze(): + """ + It creates a file called "requirements.txt" and writes the string "black" to it + """ + + module_base = """black""" + with open("requirements.txt", "w") as f: + f.write(module_base) + os.chmod("requirements.txt", 0o777) + print(notice + f'Successfully created the file "requirements.txt"') + + def create_file_gitignore(): + """ + It creates a file called .gitignore and writes the string "*.pyc" to it + """ + with open(".gitignore", "w") as f: + f.write(f"*.pyc\n/{env_directory()}") + os.chmod(".gitignore", 0o777) + print(notice + f'Successfully created the file ".gitignore"') + + def update_file_readme_md(): + """ + It update a file called readme.md and writes the markdown text to it + """ + markdown_path = "readme.md" + with open(markdown_path, "r", encoding="utf-8") as f: + data = f.readlines() + + for i, v in enumerate(data): + if "" in v: + first = i + + if "" in v: + last = i + + data = data[: first + 1] + data[last:] + + for i, v in enumerate(data): + if "" in v: + data[ + i + ] = """ + +```bash +. +└── {}/ +{} +``` +""".format( + name, generate_tree(".") + ) + with open(markdown_path, "w", encoding="utf-8") as f: + f.writelines(data) + os.chmod(markdown_path, 0o777) + + """ + create_file_base main call function + """ + if state == "create": + create_file_main_py() + create_file_freeze() + create_file_gitignore() + create_file_readme_md() + update_file_readme_md() + elif state == "update": + update_file_readme_md() + + """ + end of create_file_base function + """ diff --git a/fenv/customizes/colors.py b/fenv/customizes/colors.py new file mode 100644 index 0000000..81106f4 --- /dev/null +++ b/fenv/customizes/colors.py @@ -0,0 +1,112 @@ +class Colors: + """ + It's a class that contains a bunch of constants that represent colors. + Example: + Colors.RED + Colors.GREEN + Colors.YELLOW + Colors.BLUE + Colors.CYAN + Colors.MAGENTA + Colors.WHITE + + + """ + + ESCAPE_SEQ = { + "HEADER": "\033[95m", + "OKBLUE": "\033[94m", + "OKGREEN": "\033[92m", + "WARNING": "\033[93m", + "FAIL": "\033[91m", + "ENDC": "\033[0m", + "BOLD": "\033[1m", + "UNDERLINE": "\033[4m", + } + + TEXT_COLORS = { + "BLACK": "\033[30m", + "RED": "\033[31m", + "GREEN": "\033[32m", + "YELLOW": "\033[33m", + "BLUE": "\033[34m", + "MAGENTA": "\033[35m", + "CYAN": "\033[36m", + "WHITE": "\033[37m", + } + + LIGHT_COLORS = { + "LIGHTBLACK_EX": "\033[90m", + "LIGHTRED_EX": "\033[91m", + "LIGHTGREEN_EX": "\033[92m", + "LIGHTYELLOW_EX": "\033[93m", + "LIGHTBLUE_EX": "\033[94m", + "LIGHTMAGENTA_EX": "\033[95m", + "LIGHTCYAN_EX": "\033[96m", + "LIGHTWHITE_EX": "\033[97m", + } + + COLOR256 = { + "PURPLE": "\033[38;5;129m", + "ORANGE": "\033[38;5;202m", + "BROWN": "\033[38;5;130m", + "OLIVE": "\033[38;5;142m", + "GOLD": "\033[38;5;214m", + "SILVER": "\033[38;5;188m", + "MAROON": "\033[38;5;52m", + "NAVY": "\033[38;5;21m", + "TEAL": "\033[38;5;29m", + "LIME": "\033[38;5;118m", + "AQUA": "\033[38;5;45m", + "FUSCHIA": "\033[38;5;161m", + "PURPLE2": "\033[38;5;98m", + "PLUM": "\033[38;5;88m", + "INDIGO": "\033[38;5;54m", + "TURQUOISE": "\033[38;5;80m", + "STEEL_BLUE": "\033[38;5;67m", + "ROSE": "\033[38;5;210m", + "HOT_PINK": "\033[38;5;200m", + "SALMON": "\033[38;5;173m", + "CORAL": "\033[38;5;203m", + "BEIGE": "\033[38;5;230m", + "KHAKI": "\033[38;5;143m", + "FOREST_GREEN": "\033[38;5;34m", + "OLIVE_GREEN": "\033[38;5;58m", + "LAVENDER": "\033[38;5;183m", + "ORCHID": "\033[38;5;170m", + "LILAC": "\033[38;5;134m", + "SKY_BLUE": "\033[38;5;117m", + "BABY_BLUE": "\033[38;5;152m", + "POWDER_BLUE": "\033[38;5;165m", + "SEA_GREEN": "\033[38;5;27m", + "PALE_GREEN": "\033[38;5;120m", + "SPRING_GREEN": "\033[38;5;48m", + "MINT_GREEN": "\033[38;5;121m", + "GRAY_BLUE": "\033[38;5;103m", + "BLUE_GRAY": "\033[38;5;104m", + } + + def __getattr__(self, name): + if name in self.ESCAPE_SEQ: + return self.ESCAPE_SEQ[name] + elif name in self.TEXT_COLORS: + return self.TEXT_COLORS[name] + elif name in self.LIGHT_COLORS: + return self.LIGHT_COLORS[name] + elif name in self.COLOR256: + return self.COLOR256[name] + else: + raise AttributeError + + def notice(self): + return ( + self.OKBLUE + + "[" + + self.ENDC + + self.OKGREEN + + "notice" + + self.OKBLUE + + "]" + + self.ENDC + + " " + ) diff --git a/fenv/env_all.py b/fenv/env_all.py new file mode 100644 index 0000000..cd278ca --- /dev/null +++ b/fenv/env_all.py @@ -0,0 +1,28 @@ +""" Module about passing folder names """ +import fnmatch +import os + + +class EnvAll: + def __init__(self, **kwargs): + self.kwargs = kwargs + + def get_env_name(self): + """It's a function that checks if the environment directory exists. + Return: + [] : empyt list + """ + self.folder_name = "env*" + return ( + fnmatch.filter(os.listdir("."), self.folder_name) + if fnmatch.filter(os.listdir("."), self.folder_name) == [] + else str(fnmatch.filter(os.listdir("."), self.folder_name)[0]) + ) + + def get_root_dir_name(): + """It's a function that checks if the root directory exists. + + Return: + str : root directory + """ + return os.path.basename(os.path.abspath(".")) diff --git a/fenv/fenv.py b/fenv/fenv.py index 54f50f3..f57c9c9 100644 --- a/fenv/fenv.py +++ b/fenv/fenv.py @@ -1,55 +1,139 @@ from argparse import ArgumentParser +from dotenv import load_dotenv import os import platform import re import random +import fnmatch + +load_dotenv() + + +# It's a class that contains a bunch of constants that represent colors. +class Colors: + ESCAPE_SEQ = { + "HEADER": "\033[95m", + "OKBLUE": "\033[94m", + "OKGREEN": "\033[92m", + "WARNING": "\033[93m", + "FAIL": "\033[91m", + "ENDC": "\033[0m", + "BOLD": "\033[1m", + "UNDERLINE": "\033[4m", + } + + TEXT_COLORS = { + "BLACK": "\033[30m", + "RED": "\033[31m", + "GREEN": "\033[32m", + "YELLOW": "\033[33m", + "BLUE": "\033[34m", + "MAGENTA": "\033[35m", + "CYAN": "\033[36m", + "WHITE": "\033[37m", + } + + LIGHT_COLORS = { + "LIGHTBLACK_EX": "\033[90m", + "LIGHTRED_EX": "\033[91m", + "LIGHTGREEN_EX": "\033[92m", + "LIGHTYELLOW_EX": "\033[93m", + "LIGHTBLUE_EX": "\033[94m", + "LIGHTMAGENTA_EX": "\033[95m", + "LIGHTCYAN_EX": "\033[96m", + "LIGHTWHITE_EX": "\033[97m", + } + + COLOR256 = { + "PURPLE": "\033[38;5;129m", + "ORANGE": "\033[38;5;202m", + "BROWN": "\033[38;5;130m", + "OLIVE": "\033[38;5;142m", + "GOLD": "\033[38;5;214m", + "SILVER": "\033[38;5;188m", + "MAROON": "\033[38;5;52m", + "NAVY": "\033[38;5;21m", + "TEAL": "\033[38;5;29m", + "LIME": "\033[38;5;118m", + "AQUA": "\033[38;5;45m", + "FUSCHIA": "\033[38;5;161m", + "PURPLE2": "\033[38;5;98m", + "PLUM": "\033[38;5;88m", + "INDIGO": "\033[38;5;54m", + "TURQUOISE": "\033[38;5;80m", + "STEEL_BLUE": "\033[38;5;67m", + "ROSE": "\033[38;5;210m", + "HOT_PINK": "\033[38;5;200m", + "SALMON": "\033[38;5;173m", + "CORAL": "\033[38;5;203m", + "BEIGE": "\033[38;5;230m", + "KHAKI": "\033[38;5;143m", + "FOREST_GREEN": "\033[38;5;34m", + "OLIVE_GREEN": "\033[38;5;58m", + "LAVENDER": "\033[38;5;183m", + "ORCHID": "\033[38;5;170m", + "LILAC": "\033[38;5;134m", + "SKY_BLUE": "\033[38;5;117m", + "BABY_BLUE": "\033[38;5;152m", + "POWDER_BLUE": "\033[38;5;165m", + "SEA_GREEN": "\033[38;5;27m", + "PALE_GREEN": "\033[38;5;120m", + "SPRING_GREEN": "\033[38;5;48m", + "MINT_GREEN": "\033[38;5;121m", + "GRAY_BLUE": "\033[38;5;103m", + "BLUE_GRAY": "\033[38;5;104m", + } + + def __getattr__(self, name): + if name in self.ESCAPE_SEQ: + return self.ESCAPE_SEQ[name] + elif name in self.TEXT_COLORS: + return self.TEXT_COLORS[name] + elif name in self.LIGHT_COLORS: + return self.LIGHT_COLORS[name] + elif name in self.COLOR256: + return self.COLOR256[name] + else: + raise AttributeError -class bcolors: - """It's a class that contains a bunch of variables that are strings of ANSI escape codes. - Example: - ``` - bcolors.HEADER - bcolors.OKBLUE - bcolors.OKGREEN - bcolors.WARNING - bcolors.FAIL - bcolors.ENDC - ``` - Return: - None - """ - - HEADER = "\033[95m" - OKBLUE = "\033[94m" - OKGREEN = "\033[92m" - WARNING = "\033[93m" - FAIL = "\033[91m" - ENDC = "\033[0m" - - def __init__(self): - self.HEADER = "" - self.OKBLUE = "" - self.OKGREEN = "" - self.WARNING = "" - self.FAIL = "" - self.ENDC = "" - - +Colors = Colors() # Defining a variable called notice. notice = ( - bcolors.OKBLUE + Colors.OKBLUE + "[" - + bcolors.ENDC - + bcolors.OKGREEN + + Colors.ENDC + + Colors.OKGREEN + "notice" - + bcolors.OKBLUE + + Colors.OKBLUE + "]" - + bcolors.ENDC + + Colors.ENDC + " " ) +def env_directory(): + """It's a function that checks if the environment directory exists. + Return: + [] : empyt list + """ + folder_name = "env*" + return ( + fnmatch.filter(os.listdir("."), folder_name) + if fnmatch.filter(os.listdir("."), folder_name) == [] + else str(fnmatch.filter(os.listdir("."), folder_name)[0]) + ) + + +def root_directory(): + """It's a function that checks if the root directory exists. + + Return: + str : root directory + """ + return os.path.basename(os.path.abspath(".")) + + def create_dir_file(path, text): """It creates a directory if it doesn't exist, and then creates a file in that directory with the given text @@ -110,35 +194,35 @@ def create_folder(folder_name): def create_setting_vscode(env_path): """ - It creates a file called settings.json in a directory called .vscode. - - The file contains a JSON object with two keys: - + It creates a file called settings.json in a directory called .vscode. + + The file contains a JSON object with two keys: + - python.formatting.provider - python.pythonPath - - The value of the first key is the string "black". - - The value of the second key is the path to the virtual environment. - - The function also prints a message to the console. - - The message is a string that contains the value of the global variable notice. - - The message also contains the string "Successfully created the .vscode/settings.json". - - The function ends with the keyword def. - - The function is called create_setting_vscode. - - The function takes one argument. - - The argument is called env_path. - - The function begins with the keyword def. - + + The value of the first key is the string "black". + + The value of the second key is the path to the virtual environment. + + The function also prints a message to the console. + + The message is a string that contains the value of the global variable notice. + + The message also contains the string "Successfully created the .vscode/settings.json". + + The function ends with the keyword def. + + The function is called create_setting_vscode. + + The function takes one argument. + + The argument is called env_path. + + The function begins with the keyword def. + The function ends with the - + Args: env_path (str): The path to the virtual environment Example: @@ -154,12 +238,13 @@ def create_setting_vscode(env_path): print(notice + f"Successfully created the .vscode/settings.json") -def create_file_base(name): +def create_file_base(name, state): """ It creates a file called main.py and writes a function called main() inside of it Args: name (str): The name of the project + state (str): The state of the project Example: ```py create_file_base("project_name") @@ -187,6 +272,28 @@ def main(): os.chmod(file_path, 0o777) print(notice + f'Successfully created the file "{file_path}"') + def generate_tree(startpath): + output = "" + for root, dirs, files in os.walk(startpath): + level = root.replace(startpath, "").count(os.sep) + if level == 0: + indent = " " * (level + 1) + "│ " + subindent = " " * (level + 2) + for d in dirs: + dir_path = os.path.join(root, d) + output += f"{subindent}{'└──'}{d}/\n" + if d == ".vscode": + output += f"{subindent}{subindent}{'└──'}settings.json\n" + if d == env_directory(): + for i in ["Lib/", "Scripts", ".gitignore", "pyvenv.cfg"]: + output += f"{subindent}{subindent}{'└──'} {i}\n" + + for f in files: + file_path = os.path.join(root, f) + output += f"{subindent}{'└──'}{f}\n" + print(os.getcwd()) + return output + def create_file_readme_md(): """ It creates a file called readme.md and writes the markdown text to it @@ -194,7 +301,6 @@ def create_file_readme_md(): markdown_path = "readme.md" markdown = """ # {} - A brief and descriptive title for your project. ## Description @@ -204,13 +310,36 @@ def create_file_readme_md(): ## Getting Started ``` -pip install -r requirements.txt +git clone https://github.com//{}.git + +cd {} + +``` + +## Installation + +``` +# create virtualenv auto name +fenv onlyenv + +# install package in requirements.txt +fenv install + ``` ## Usage Instructions on how to use the project, including any usage examples and screenshots. +## Tree + +```bash +. +└── {}/ +{} +``` + + ## Contributing If you would like to contribute to the project, include a section on how to do so, including any guidelines and best practices. @@ -220,8 +349,8 @@ def create_file_readme_md(): Include information about the license used for the project, such as the name of the license (e.g. MIT, Apache 2.0, etc.) and a link to the license text. """ - with open(markdown_path, "w") as f: - f.write(markdown.format(name)) + with open(markdown_path, "w", encoding="utf-8") as f: + f.write(markdown.format(name, name, name, name, generate_tree("."))) os.chmod(markdown_path, 0o777) print(notice + f'Successfully created the file "{markdown_path}"') @@ -236,12 +365,65 @@ def create_file_freeze(): os.chmod("requirements.txt", 0o777) print(notice + f'Successfully created the file "requirements.txt"') - create_file_main_py() - create_file_readme_md() - create_file_freeze() + def create_file_gitignore(): + """ + It creates a file called .gitignore and writes the string "*.pyc" to it + """ + with open(".gitignore", "w") as f: + f.write(f"*.pyc\n/{env_directory()}") + os.chmod(".gitignore", 0o777) + print(notice + f'Successfully created the file ".gitignore"') + + def update_file_readme_md(): + """ + It update a file called readme.md and writes the markdown text to it + """ + markdown_path = "readme.md" + with open(markdown_path, "r", encoding="utf-8") as f: + data = f.readlines() + + for i, v in enumerate(data): + if "" in v: + first = i + + if "" in v: + last = i + + data = data[: first + 1] + data[last:] + + for i, v in enumerate(data): + if "" in v: + data[ + i + ] = """ + +```bash +. +└── {}/ +{} +``` +""".format( + name, generate_tree(".") + ) + with open(markdown_path, "w", encoding="utf-8") as f: + f.writelines(data) + os.chmod(markdown_path, 0o777) + """ + create_file_base main call function + """ + if state == "create": + create_file_main_py() + create_file_freeze() + create_file_gitignore() + create_file_readme_md() + update_file_readme_md() + elif state == "update": + update_file_readme_md() -"" + """ + end of create_file_base function + """ def run_install_module_base(env): @@ -279,7 +461,7 @@ def create_project_all(name): print(notice + "Creating...") create_virtualenv(name) create_setting_vscode(name) - create_file_base(name) + create_file_base(name, "create") run_install_module_base(name) @@ -338,7 +520,7 @@ def cmd_install_package(args): try: if platform.system() == "Windows": os.system( - f".\{name_env()}\Scripts\python.exe -m pip install {args.install}" + f".\{env_directory()}\Scripts\python.exe -m pip install {args.install}" ) print(notice + f"Successfully installed module {args.install}") except TimeoutError: @@ -359,8 +541,13 @@ def add_module_to_txt(args): None """ - os.system(f"pip freeze > requirements.txt") - print(notice + f'Successfully module {args.install} added to "requirements.txt"') + if env_directory(): + os.system( + f".\{env_directory()}\Scripts\python.exe -m pip freeze > requirements.txt" + ) + print( + notice + f'Successfully module {args.install} added to "requirements.txt"' + ) def find_dir_env() -> str: @@ -378,7 +565,7 @@ def find_dir_env() -> str: def install_package(args): """ It takes a list of packages, and installs them using the `pip` command - + Args: args (str): The arguments passed to the command Example: @@ -409,7 +596,7 @@ def cmd_uninstall_package(args): try: if platform.system() == "Windows": os.system( - f".\{name_env()}\Scripts\python.exe -m pip uninstall {args.uninstall}" + f".\{env_directory()}\Scripts\python.exe -m pip uninstall {args.uninstall}" ) print(notice + f"Successfully uninstalled module {args.uninstall}") except TimeoutError: @@ -419,7 +606,7 @@ def cmd_uninstall_package(args): def remove_module_exit_txt(args): """ It removes the module from the requirements.txt file - + Args: args (str): This is the argument that is passed to the function. Example: @@ -443,7 +630,7 @@ def remove_module_exit_txt(args): def uninstall_package(args): """ It will uninstall the package and remove the module exit text file - + Args: args (str): The arguments passed to the script. Example: @@ -474,7 +661,11 @@ def setup_parse(): "new", type=str, help="The name of the project", nargs="?", default=None ) - install_cmd = subparsers.add_parser("install", help="Install packages") + install_cmd = subparsers.add_parser( + "install", + help="Install the package and install the package via requirements.txt", + usage=f"{Colors.NAVY}fenv install {Colors.NAVY}{Colors.ENDC} or {Colors.HOT_PINK}fenv install {Colors.ENDC}", + ) install_cmd.add_argument( "install", type=str, @@ -483,7 +674,11 @@ def setup_parse(): default=None, ) - uninstall_cmd = subparsers.add_parser("uninstall", help="Uninstall packages") + uninstall_cmd = subparsers.add_parser( + "uninstall", + help="Uninstall packages", + usage=f"{Colors.HOT_PINK}fenv uninstall {Colors.ENDC}", + ) uninstall_cmd.add_argument( "uninstall", type=str, @@ -493,11 +688,15 @@ def setup_parse(): ) update_cmd = subparsers.add_parser( - "update", help="Update packages to file requirements.txt" + "update", + help="Package to file requirements.txt update furthermore, update the readme.md file's tree path.", + usage=f"{Colors.HOT_PINK}fenv update{Colors.ENDC}", ) onlyenv_cmd = subparsers.add_parser( - "onlyenv", help="Create only virtualenv and no create base file" + "onlyenv", + help=f"Create only virtualenv and no create base file", + usage=f"{Colors.HOT_PINK}fenv onlyenv{Colors.ENDC}", ) # clean_cmd = subparsers.add_parser( @@ -508,6 +707,9 @@ def setup_parse(): general_group.add_argument( "-h", "--help", action="help", help="Show this help message and exit" ) + general_group.add_argument( + "-v", "--version", action="store_true", help="check version fenv" + ) args = parser.parse_args() @@ -517,7 +719,7 @@ def setup_parse(): def run_cmd_new(args): """ It creates a new project folder and then creates a virtual environment inside that folder - + Args: args (str): The arguments passed to the command. Example: @@ -534,11 +736,11 @@ def run_cmd_new(args): print( "Maybe you forgot to enter the name of the folder? for example" + " `" - + bcolors.OKGREEN + + Colors.LIGHTGREEN_EX + "fenv new" - + bcolors.OKBLUE + + Colors.NAVY + " " - + bcolors.ENDC, + + Colors.ENDC, "`", ) @@ -546,7 +748,7 @@ def run_cmd_new(args): def run_cmd_install(args): """ It tries to install a package, if it fails, it prints a message - + Args: args (str): The arguments passed to the command. Example: @@ -558,23 +760,108 @@ def run_cmd_install(args): """ try: - print("Installing...") - install_package(args) + if env_directory(): + install_package(args) + else: + while True: + response = input( + "We couldn't find the fenv virtual environment. Would you like to set up a new one? (y/n): " + ) + if ( + response.lower() == "y" + or response.lower() == "yes" + or response.lower() == "" + ): + run_cmd_onlyenv() + folder_name = "env*" + folder_name_env = str( + fnmatch.filter(os.listdir("."), folder_name)[0] + ) + install_package(args) + break + elif response.lower() == "n": + install_package(args) + break except AttributeError as err: print( - bcolors.OKGREEN + Colors.LIGHTGREEN_EX + "An error was encountered, it could not be installed." - + bcolors.ENDC + + Colors.ENDC + ) + + +def install_package_all(): + """ + install all packages in requirements.txt file using pip install -r requirements.txt + """ + + folder_name = "env*" + folder_name_env = ( + fnmatch.filter(os.listdir("."), folder_name) + if fnmatch.filter(os.listdir("."), folder_name) == [] + else str(fnmatch.filter(os.listdir("."), folder_name)[0]) + ) + requirements_file = "requirements.txt" + + def install_package_follow_env(folder_name_env): + if platform.system() == "Windows": + os.system( + f".\{folder_name_env}\Scripts\python.exe -m pip install -r requirements.txt" + ) + + def run_install_main(folder_name_env): + if folder_name_env: + print( + f"Found directory `{Colors.LIGHTGREEN_EX}{folder_name_env}{Colors.ENDC}`" + ) + print( + f"Installing modules with `{Colors.LIGHTGREEN_EX}{folder_name_env}{Colors.ENDC}`" + ) + install_package_follow_env(folder_name_env) + print(notice + f'Successfully installed module from "requirements.txt"') + else: + while True: + response = input( + "We couldn't find the fenv virtual environment. Would you like to set up a new one? (y/n): " + ) + if ( + response.lower() == "y" + or response.lower() == "yes" + or response.lower() == "" + ): + run_cmd_onlyenv() + folder_name = "env*" + folder_name_env = str( + fnmatch.filter(os.listdir("."), folder_name)[0] + ) + print( + f"Installing modules with `{Colors.LIGHTGREEN_EX}{folder_name_env}{Colors.ENDC}`" + ) + install_package_follow_env(folder_name_env) + print( + notice + + f'Successfully installed module from "requirements.txt"' + ) + break + elif response.lower() == "n": + os.system(f"pip install -r requirements.txt") + break + + if requirements_file in os.listdir("."): + run_install_main(folder_name_env) + else: + print( + f"Maybe you forgot to put the name of the package to ininstall? for example `{Colors.LIGHTGREEN_EX}fenv ininstall{Colors.OKBLUE} {Colors.ENDC}` \nOr you can use `{Colors.LIGHTGREEN_EX}fenv ininstall{Colors.ENDC}` alone. But there must be {Colors.FAIL}{requirements_file}{Colors.ENDC} in the current directory" ) def run_cmd_uninstall(args): """ "A function that is called when the user runs the command "uninstall"." - + The first line of the function is a docstring. It's a string that describes what the function does. It's a good idea to include a docstring for every function you write - + Args: args (str): The arguments passed to the command Example: @@ -586,7 +873,7 @@ def run_cmd_uninstall(args): """ try: print(notice + "Uninstalling...") - # uninstall_package(args) + uninstall_package(args) except AttributeError as err: print(err, "An error was encountered, it could not be uninstalled.") @@ -599,7 +886,6 @@ def run_cmd_onlyenv(): None """ - def create_name_env_auto() -> str: """ > It creates a random name for the environment @@ -634,7 +920,7 @@ def is_english_only(s): def create_virtualenv(virtual_env_name): """ It creates a virtual environment with the name you pass to it - + Args: virtual_env_name (str): The name of the virtual environment you want to create. @@ -654,9 +940,9 @@ def create_virtualenv(virtual_env_name): print(notice + f'Successfully created the virtualenv "{virtual_env_name}"') _name_env = create_name_env() - print(f"your env name is `{bcolors.OKGREEN}{_name_env}{bcolors.ENDC}`") + print(f"your env name is `{Colors.LIGHTGREEN_EX}{_name_env}{Colors.ENDC}`") create_virtualenv(_name_env) - dir_name_only = os.path.basename(os.getcwd()) # get name dir main + dir_name_only = os.path.basename(os.getcwd()) # get name dir main create_setting_vscode(dir_name_only) @@ -687,35 +973,29 @@ def check_command(args): if args.__dict__["command"] == "new": run_cmd_new(args) elif args.__dict__["command"] == "install": - run_cmd_install(args) if args.install != None else print( - "Maybe you forgot to put the name of the package to install? for example" - + " `" - + bcolors.OKGREEN - + "fenv install" - + bcolors.OKBLUE - + " " - + bcolors.ENDC - + "`" - ) + run_cmd_install(args) if args.install != None else install_package_all() + elif args.__dict__["command"] == "uninstall": run_cmd_uninstall(args) if args.uninstall != None else print( "Maybe you forgot to put the name of the package to uninstall? for example" + " `" - + bcolors.OKGREEN + + Colors.LIGHTGREEN_EX + "fenv uninstall" - + bcolors.OKBLUE + + Colors.OKBLUE + " " - + bcolors.ENDC + + Colors.ENDC + "`" ) elif args.__dict__["command"] == "update": + create_file_base(root_directory(), "update") + print(notice + "Updated tree path to readme.md") os.system("pip freeze > requirements.txt") print(notice + "Updated module all to requirements.txt") elif args.__dict__["command"] == "onlyenv": run_cmd_onlyenv() - elif args.__dict__["command"] == "clean": - run_cmd_clean() + # elif args.__dict__["command"] == "clean": + # run_cmd_clean() def main(): @@ -725,10 +1005,21 @@ def main(): None """ args = setup_parse() - version: str = "v0.0.11" - print(f"⏩ fenv {version}") if args.__dict__["command"] == None else None + version: str = os.getenv("FENV_VERSION") + print( + f"⏩ {Colors.LIGHTMAGENTA_EX}Hello,Fenv {Colors.POWDER_BLUE}[{Colors.MINT_GREEN}v{version}{Colors.POWDER_BLUE}]{Colors.ENDC}🫡\n".center( + 40, "-" + ) + ) if args.__dict__["command"] == None else None check_command(args) + # Colors.HEADER + # Colors.OKBLUE + # Colors.OKGREEN + # Colors.WARNING + # Colors.FAIL + # Colors.ENDC + # It's a way to make sure that the code in the `main` function is only run when the script is run. # if __name__ == "__main__": diff --git a/readme.md b/readme.md index 62a32db..bf0318f 100644 --- a/readme.md +++ b/readme.md @@ -14,43 +14,58 @@ Fenv is a simple and efficient tool to help you manage your virtual environments - Packages can be installed and uninstalled and added to files. requirements.txt at the same time ## Docs + https://watchakorn-18k.github.io/Fenv/ ## Installer + ``` pip install fenv ``` + or + ``` pip install --upgrade fenv ``` +## PyPi + +``` +https://pypi.org/project/Fenv/ +``` + ## Start ```sh fenv new ``` - ## Command ```cmd $ fenv -h +usage: fenv [-h] [-v] ... + Usage: - fenv [options] + fenv Commands: - new Create a new project - install Install packages - uninstall Uninstall packages - update Update packages to file requirements.txt - onlyenv Create only virtualenv and no create base file + new Create a new project + install Install the package and install the + package via requirements.txt + uninstall Uninstall packages + update Package to file requirements.txt update + furthermore, update the readme.md file's + tree path. + onlyenv Create only virtualenv and no create + base file General Options: - -h, --help Show this help message and exit - + -h, --help Show this help message and exit + -v, --version check version fenv ``` ## Build @@ -71,20 +86,40 @@ Fenv is a powerful tool for managing virtual environments and creating basic Pyt ## Changelog +### 0.0.11.6 + +- [x] Fix bug create readme.md change `env_directory()` to `name` + ### 0.0.11.5 -- [ ] added after use `fenv onlyenv` created settings then activate env one time + +- [x] Added Tree path in md after generating projects , can you try command `fenv update` ![](https://i.imgur.com/vDz2Gs0.gif) +- [x] Added create file .gitignore +- [x] Edit readme.md small changes +- [x] Fix if an `env` folder does not exist, the modified `fenv install ` command will prompt you to confirm whether you would like to create a new `env`. If you choose not to create a new `env`, the installation will proceed using `python main` ![](https://i.imgur.com/M0shh8x.gif) +- [x] Added command `fenv install` alone will install file requirements.txt in directory current ![](https://i.imgur.com/cgApbCa.gif) +- [x] Added after use `fenv onlyenv` created settings then activate env one time ![](https://i.imgur.com/mwEUSrg.gif) + ### 0.0.11.4 -- [x] fix bugs small + +- [x] Fix bugs small + ### 0.0.11.3 -- [x] fix bugs settings in .vscode -- [x] fix bugs line 609 and 624 + +- [x] Fix bugs settings in .vscode +- [x] Fix bugs line 609 and 624 + ### 0.0.11.2 -- [x] fix bugs small + +- [x] Fix bugs small + ### 0.0.11.1 -- [x] change new pattern command `-onlyenv` to `onlyenv` + +- [x] Change new pattern command `-onlyenv` to `onlyenv` + ### 0.0.10 -- [x] add option `-onlyenv` for create only virtualenv without base file all -- [X] add command install for install package and add module to file requirements.txt + +- [x] Add option `-onlyenv` for create only virtualenv without base file all +- [x] Add command install for install package and add module to file requirements.txt ### 0.0.9 diff --git a/setup.py b/setup.py index 29a7dc6..552bff0 100644 --- a/setup.py +++ b/setup.py @@ -8,9 +8,11 @@ with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as fh: long_description = "\n" + fh.read() -VERSION = '0.0.11.4' -DESCRIPTION = 'Generate a folder, establish a virtual environment with a single command.' -LONG_DESCRIPTION = 'Generate a folder, establish a virtual environment, and simultaneously create the essential basic Python files, all with a single command' +VERSION = "0.0.11.6" +DESCRIPTION = ( + "Generate a folder, establish a virtual environment with a single command." +) +LONG_DESCRIPTION = "Generate a folder, establish a virtual environment, and simultaneously create the essential basic Python files, all with a single command" # Setting up setup( @@ -22,13 +24,12 @@ long_description_content_type="text/markdown", long_description=long_description, packages=find_packages(), - install_requires=['virtualenv'], + install_requires=["virtualenv"], entry_points=""" [console_scripts] fenv=fenv.fenv:main """, - keywords=['python', 'virtualenv', 'create file', - 'create folder', 'fenv', 'wk-18k'], + keywords=["python", "virtualenv", "create file", "create folder", "fenv", "wk-18k"], classifiers=[ "Development Status :: 1 - Planning", "Intended Audience :: Developers", @@ -36,5 +37,5 @@ "Operating System :: Unix", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", - ] + ], ) diff --git a/test.py b/test.py index 0e91220..8b4e511 100644 --- a/test.py +++ b/test.py @@ -1,3 +1 @@ -from fenv.fenv import main - -main() +from fenv import fenv