From 5c1f6331d121bc71e62c3b1a49282fc3c5c6c48e Mon Sep 17 00:00:00 2001 From: CaidevOficial Date: Thu, 24 Feb 2022 13:53:17 -0300 Subject: [PATCH 1/3] Update Readme --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index f253443..ad2ff0e 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,21 @@ + + +
+ Matplotlib Logo +
+ + + + +
+ NumPy Logo + +
+ +
From 8e53a4fc6f27c64bedc9b01be21eb3646fcf6ea5 Mon Sep 17 00:00:00 2001 From: CaidevOficial Date: Sun, 27 Feb 2022 22:32:17 -0300 Subject: [PATCH 2/3] deleted old files --- GithubCloner2022.py | 106 ------ Modules/DataFrameHandler_Mod/DFHandler.py | 245 ------------- Modules/DataManager_Mod/DataManager.py | 398 --------------------- Modules/DirectoryManager_Mod/DirManager.py | 58 --- Modules/GetData_Mod/DataManager.py | 380 -------------------- Modules/GetData_Mod/__init__.py | 16 - Modules/PlotManager_Mod/PlotManager.py | 204 ----------- Modules/PrintMessage_Mod/CloneMessenger.py | 84 ----- 8 files changed, 1491 deletions(-) delete mode 100644 GithubCloner2022.py delete mode 100644 Modules/DataFrameHandler_Mod/DFHandler.py delete mode 100644 Modules/DataManager_Mod/DataManager.py delete mode 100644 Modules/DirectoryManager_Mod/DirManager.py delete mode 100644 Modules/GetData_Mod/DataManager.py delete mode 100644 Modules/GetData_Mod/__init__.py delete mode 100644 Modules/PlotManager_Mod/PlotManager.py delete mode 100644 Modules/PrintMessage_Mod/CloneMessenger.py diff --git a/GithubCloner2022.py b/GithubCloner2022.py deleted file mode 100644 index e11e856..0000000 --- a/GithubCloner2022.py +++ /dev/null @@ -1,106 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import datetime -import pandas as pd - -from Modules.DataFrameHandler_Mod.DFHandler import DataFrameHandler as DfH -from Modules.DataManager_Mod.DataManager import DataManager as DM -from Modules.DirectoryManager_Mod.DirManager import DirectoryManager as DirM -from Modules.Formatter_Mod.Formatter import Formatter as FMT -from Modules.PlotManager_Mod.PlotManager import PlotManager as Plot -from Modules.PrintMessage_Mod.CloneMessenger import CloneMessenger as CM - -# ?######### Start Basic Configuration ########## -filename = 'Github_Repositories.csv' -name = 'Github Repository Cloner' -version = '[V2.1.1]' -author = '[FacuFalcone - CaidevOficial]' -fileConfigName = 'Modules/API_Info.json' -# ?######### End Basic Configuration ########## - -if __name__ == '__main__': - - start_time = datetime.datetime.now() - try: - # ?#########? Start Initialization ########## - JsonFile = pd.read_json(f"./{fileConfigName}", orient='records') - JsonAPI = JsonFile['Github'] - JsonDFConfigs = JsonFile['DataFrame']['Fields'] - JsonDirConfigs = JsonFile['Files'] - # ?#########? End Initialization ############ - - # ?#########? Start Objects Instances ########## - Handler = DfH() - Manager = DM() - Messenger = CM() - Timer = FMT() - Plotter = Plot() - DirManager = DirM() - # ?#########? End Objects Instances ########## - - # ?#########? Start Directory Creation ########## - DirManager.PathToCreate = JsonDirConfigs['Dir_Plots_img'] - DirManager.createDirIfNoExist() - - DirManager.PathToCreate = JsonDirConfigs['Dir_Cloned_Repos'] - DirManager.createDirIfNoExist() - # ?#########? End Directory Creation ########## - - # ?#########? Start DataManager Configuration ########## - Manager.InitialConfig(name, version, author, JsonAPI, JsonDirConfigs['Dir_Cloned_Repos']) - # ?#########? End DataManager Configuration ########## - - # ?#########? Start DataFrame Configuration ########## - # *# Reads the 'csv' File to get the dataframe - df = pd.read_csv(filename) - - # *# Sets the Main DF to the class to handle it - Handler.MainDataFrame = df - Handler.ConfigsJsonValues = JsonDFConfigs - Handler.ConfigurateDataFrame(Handler.ConfigsJsonValues['Course']) - # ?#########? End DataFrame Configuration ########## - - # ?#########? Start Initialize DataManager ########## - Manager.CloneRepositories(Handler) - # ?##########? End Initialize DataManager ########### - - # ?#########? Start PlotManager Configuration ########## - Plotter.initialize(Handler, 'Repositories to Clone', JsonDirConfigs['Dir_Plots_img']) - - except Exception as e: - print(f'Exception: {e.args}') - finally: - # ?#########? Start Timer Config ########## - Timer.CrudeTime = start_time - # ?#########? End Timer Config ########## - # ?#########? Start Print Message ########## - Messenger.Message = f"Elapsed Time: {Timer.FormattedTimeStr}" - Messenger.PrintMessage() - - Messenger.Message = f"Thanks for using {name} {version} by {author}! ♥" - Messenger.PrintMessage() - - Messenger.Message = "Creating Pie Chart..." - Messenger.PrintMessage() - Plotter.createPieChart() - - Messenger.Message = "Success! All task done. Press a key to close the app" - Messenger.PrintMessage() - # ?#########? End Print Message ########## - - end = input() diff --git a/Modules/DataFrameHandler_Mod/DFHandler.py b/Modules/DataFrameHandler_Mod/DFHandler.py deleted file mode 100644 index 5fd36c6..0000000 --- a/Modules/DataFrameHandler_Mod/DFHandler.py +++ /dev/null @@ -1,245 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from numpy import ndarray -from pandas import DataFrame - - -class DataFrameHandler: - """[summary] \n - Class in charge of configurate and handle all the dataframe operations. \n - Returns: - class: [DataFrameHandler]. \n - """ - # ?####? Attributes ##### - __configsJsonValues: dict = {} - __commands = [] - __uniqueColumns: ndarray = [] - __mainDF: DataFrame = None - __studentsDF = [] - __orderedListOfDFStudents: list = [] - # ?####? End Attributes ##### - - def __init__(self) -> None: - pass - - # ?####? Properties ##### - - @property - def OrderListOfDFStudents(self) -> list: - """[summary] \n - Get the list of ordered dataframes. \n - Returns: - [list]: [The list of ordered dataframes]. \n - """ - return self.__orderedListOfDFStudents - - @OrderListOfDFStudents.setter - def OrderListOfDFStudents(self, df: DataFrame) -> None: - """[summary] \n - Set the list of ordered dataframes. \n - Args: - df (DataFrame): [The ordered dataframes]. \n - """ - self.__orderedListOfDFStudents.append(df) - - @property - def ConfigsJsonValues(self) -> dict: - """[summary] \n - Get the configs of the json. \n - Returns: - [dict]: [The configs of the json]. \n - """ - return self.__configsJsonValues - - @ConfigsJsonValues.setter - def ConfigsJsonValues(self, value: dict) -> None: - """[summary] \n - Set the configs of the json. \n - Args: - value (dict): [The configs of the json]. \n - """ - self.__configsJsonValues = value - - @property - def MainDataFrame(self) -> DataFrame: - """[summary] \n - Get the main dataframe. \n - Returns: - [DataFrame]: [The main dataframe]. \n - """ - return self.__mainDF - - @MainDataFrame.setter - def MainDataFrame(self, df: DataFrame): - """[summary] \n - Set the main dataframe. \n - Args: - df (DataFrame): [The dataframe to set]. \n - """ - self.__mainDF = df - - @property - def UniqueColumns(self) -> ndarray: - """[summary] \n - Get the unique values of the column 'columnValue' [Division]. \n - Returns: - [ndarray]: [The unique values of the column 'columnValue' [Division]]. \n - """ - return self.__uniqueColumns - - @UniqueColumns.setter - def UniqueColumns(self, uniqueColumns: ndarray): - """[summary] \n - Set the unique values of the column 'columnValue' [Division]. \n - Args: - uniqueColumns (ndarray): [The unique values of the column 'columnValue' [Division]]. \n - """ - self.__uniqueColumns = uniqueColumns - - @property - def Commands(self) -> list: - """[summary] \n - Get the list of the commands. \n - Returns: - [list]: [The list of the commands]. \n - """ - return self.__commands - - @Commands.setter - def Commands(self, command: str) -> None: - """[summary] \n - Sets a command inside the list of the commands. \n - Args: - command (str): [The command to add]. \n - """ - self.__commands.append(command) - - @property - def StudentsDF(self) -> list: - """[summary] \n - Get the dataframe with the students. \n - Returns: - [DataFrame]: [The dataframe with the students]. \n - """ - return self.__studentsDF - - @StudentsDF.setter - def StudentsDF(self, df: DataFrame) -> None: - """[summary] \n - Set the dataframe with the students. \n - Args: - df (DataFrame): [The dataframe with the students]. \n - """ - self.__studentsDF.append(df) - - # ?####? End Properties ##### - - # ?####? Methods ##### - - def GetSpecificStudentsDF(self, df: DataFrame, column: str, value: str) -> DataFrame: - """[summary] \n - Get the students that have the specified index value in the specified column. \n - The DataFrame MUST be indexed by the 'value' column. \n - Args: - df (DataFrame): [The dataframe to filter]. \n - column (str): [The column to filter]. \n - value (str): [The value to filter]. \n - Returns: - [DataFrame]: [The dataframe with the filtered students ordered by Course, Surname & Name]. \n - """ - specificDF: DataFrame = df[df[column] == value] - orderedDF: DataFrame = self.OrderIndexedDFBy( - specificDF, self.ConfigsJsonValues['Course'], - self.ConfigsJsonValues['Surname'], - self.ConfigsJsonValues['Name'] - ) - return orderedDF - - def CreateListDFStudentsBy(self, df: DataFrame, column: str, columnValue: str): - """[summary] \n - Creates a list of the students that have the specified index value in the specified column. \n - The DataFrame MUST be indexed by the 'value' column. \n - Args: - df (DataFrame): [The dataframe to filter]. \n - column (str): [The column to filter]. \n - value (list): [The values to filter]. \n - """ - self.OrderListOfDFStudents = self.GetSpecificStudentsDF( - df, column, columnValue) - - def OrderIndexedDFBy(self, df: DataFrame, firstField: str, secondField: str, thirdField: str) -> DataFrame: - """[summary] \n - Order the dataframe by the specified fields. \n - Args: - df (DataFrame): [The dataframe to order]. \n - firstField (str): [The first field to order]. \n - secondField (str): [The second field to order]. \n - thirdField (str): [The third field to order]. \n - Returns: - [DataFrame]: [The dataframe ordered by the three fields in the specified order]. \n - """ - sortedDF = df.sort_values( - by=[firstField, secondField, thirdField], ascending=[True, True, True]) - return sortedDF - - def ConfigUniqueValuesInColumn(self, column: str): - """[summary] \n - Get the unique values in the specified column and sort them in alphabetical order ASC. \n - Args: - column (str): [The column to filter]. \n - Returns: - [list]: [The unique values in the specified column]. \n - """ - self.UniqueColumns = self.MainDataFrame[column].unique() - self.UniqueColumns.sort() - - def CreateJsonOfEveryDF(self): - """[summary] \n - Create a json file for every dataframe. \n - """ - - for i in range(len(self.OrderListOfDFStudents)): - frame: DataFrame = self.OrderListOfDFStudents[i] - name = frame.at[frame.index.values[0], - self.ConfigsJsonValues['Course']] - filename: str = f'{name}.json' - frame.to_json(f'{filename}', orient='table', - indent=4, force_ascii=True) - - # ?####? End Methods ##### - - # *####* Main Method ##### - - def ConfigurateDataFrame(self, columnValue: str) -> None: - """[summary] \n - Configurate the dataframe with the specified column value. \n - Args: - columnValue (str): [The column value to configurate]. \n - """ - - # *# Gets the unique values of the column 'columnValue' [Division] - self.ConfigUniqueValuesInColumn(columnValue) - # *# For each unique value of the column 'columnValue' [Division] - # *# Creates a list of dataframes with the students that have the - # *# specified value in the column 'columnValue' [Division] - for unique in self.UniqueColumns: - self.CreateListDFStudentsBy( - self.MainDataFrame, columnValue, unique) - self.CreateJsonOfEveryDF() - - # *####* End Main Method ##### diff --git a/Modules/DataManager_Mod/DataManager.py b/Modules/DataManager_Mod/DataManager.py deleted file mode 100644 index 4c2bb53..0000000 --- a/Modules/DataManager_Mod/DataManager.py +++ /dev/null @@ -1,398 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os -import requests - -from Modules.DataFrameHandler_Mod.DFHandler import DataFrameHandler as DFH -from Modules.PrintMessage_Mod.CloneMessenger import CloneMessenger as CM -from pandas import DataFrame - - -class DataManager: - """[summary] \n - Class in charge of the file management to read and process the \n - data of the students in order to clone their repositorys. \n - Returns: - [class]: [DataManager]. \n - """ - # ?########? START ATTRIBUTES ######### - __mainDir: str = '' - __configAPIURL = '' - __APIResponse = None - __APIDate = None - __name = '' - __version = '' - __author = '' - __studentsInfo: DataFrame = DataFrame() - __commands: list = [] - __Messenger: CM = CM() - __cloningMessages: list = [] - # ?#######? END ATTRIBUTES ######### - - def __init__(self): - pass - - # ?########? PROPERTIES - GET ######### - - @property - def AppAuthor(self) -> str: - """[summary] \n - Get the author of the application. \n - Returns: - str: [The author of the application]. \n - """ - return self.__author - - @property - def Messenger(self) -> CM: - """[summary] \n - Get the Messenger of the class. \n - Returns: - CM: [The Messenger of the class]. \n - """ - return self.__Messenger - - @property - def Commands(self): - """[summary] \n - Get the commands to clone the repositories of the students. \n - Returns: - list: [The list of the commands to execute]. \n - """ - return self.__commands - - @property - def APIResponse(self) -> str: - """[summary] \n - Get the API Response. \n - Returns: - str: [The API Response]. \n - """ - return self.__APIResponse - - @property - def AppName(self) -> str: - """[summary] \n - Set the name of the file. \n - Args: - name (str): [The name of the file]. \n - """ - return self.__name - - @property - def AppVersion(self) -> str: - """[summary] \n - Get the version of the application. \n - Returns: - str: [The version of the application]. \n - """ - return self.__version - - @property - def APIURL(self) -> str: - """[summary] \n - Get the URL of the API. \n - Returns: - str: [The URL of the API]. \n - """ - return self.__configAPIURL - - @property - def StudensDF(self) -> DataFrame: - """[summary] \n - Get the dataframe with the students information. \n - Returns: - DataFrame: [The dataframe with the students information]. \n - """ - return self.__studentsInfo - - @property - def CloningMessages(self) -> list: - """[summary] \n - Get the list of the cloning messages. \n - Returns: - list: [The list of the cloning messages]. \n - """ - return self.__cloningMessages - - @property - def APIDate(self) -> str: - """[summary] \n - Get the date of the API. \n - Returns: - str: [The date of the API]. \n - """ - return self.__APIDate - - @property - def MainDir(self) -> str: - """[summary] \n - Get the main directory to save the downloaded repositories. \n - Returns: - str: [The main directory to save the downloaded repositories]. \n - """ - return self.__mainDir - - # ?########? END PROPERTIES - GET ######### - - # ?########? START PROPERTIES - SET ######### - - @AppAuthor.setter - def AppAuthor(self, author: str) -> None: - """[summary] \n - Set the author of the application. \n - Args: - author (str): [The author of the application]. \n - """ - self.__author = author - - @Commands.setter - def Commands(self, commands: list): - """[summary] \n - Set the commands to clone the repositories of the students. \n - Args: - commands (list): [The list of the commands to execute]. \n - """ - self.__commands = commands - - @APIResponse.setter - def APIResponse(self, APILink: str): - """[summary] \n - Set the API Response by sending a request trough the API link. \n - Args: - APILink (str): [The Link of the API]. \n - """ - self.__APIResponse = requests.get(APILink) - - @AppName.setter - def AppName(self, name: str) -> None: - """[summary] \n - Set the name of the file. \n - Args: - name (str): [The name of the file]. \n - """ - self.__name = name - - @AppVersion.setter - def AppVersion(self, version: str) -> None: - """[summary] \n - Set the version of the file. \n - Args: - version (str): [The version of the file]. \n - """ - self.__version = version - - @APIURL.setter - def APIURL(self, url: dict) -> None: - """[summary] \n - Set the URL of the API. \n - Args: \n - url (dict): [The json with all the fields of the API url.] \n - "URL": "https://api.github.com/repos", \n - "USER": "Your_Github_User", \n - "REPO": "Your_Repository", \n - "BRANCH": "Your_Principal_Branch" \n - Example: "https://api.github.com/repos/Your_Github_User/Your_Repository/commits/Your_Principal_Branch". \n - """ - self.__configAPIURL = f'{url["URL"]}/{url["USER"]}/{url["REPO"]}/commits/{url["BRANCH"]}' - - @StudensDF.setter - def StudensDF(self, studentsInfo: DataFrame) -> None: - """[summary] \n - Set the dataframe of students to work with. \n - Args: - studentsInfo (DataFrame): The dataframe of students to work. \n - """ - self.__studentsInfo = studentsInfo - - @CloningMessages.setter - def CloningMessages(self, cloningMessage: str): - """[summary] \n - Adds a message to the cloning messages. \n - Args: - cloningMessage (str): [The message to add]. \n - """ - self.__cloningMessages.append(cloningMessage) - - @APIDate.setter - def APIDate(self, APIResponse: str): - """[summary] \n - Set the date of the API. \n - Args: - APIResponse (str): [The response of the API Setted]. \n - """ - date = APIResponse.json()["commit"]["author"]["date"] - date = date[:10] - self.__APIDate = date.replace("-", "") - - @MainDir.setter - def MainDir(self, mainDir: str) -> None: - """[summary] \n - Set the main directory to save the downloaded repositories. \n - Args: - mainDir (str): [The main directory to save the downloaded repositories]. \n - """ - self.__mainDir = mainDir.strip() - - # ?#######? END PROPERTIES - SET ######### - - # ?########? METHODS ######### - - def InitialConfig(self, name: str, version: str, author: str, APIURL: dict, mainDir: str): - """[summary] \n - Initialize the config of the class, Also sets the API response \n - and the date of the API. \n - Args: - name (str): [The name of the program]. \n - version (str): [The version of the program]. \n - author (str): [The author of the program]. \n - APIURL (dict): [The API URL of the program]. \n - mainDir (str): [The main directory to clone repositories]. \n - """ - self.AppName = name - self.AppVersion = version - self.AppAuthor = author - self.APIURL = APIURL - self.APIResponse = self.APIURL - self.APIDate = self.APIResponse - self.MainDir = mainDir - - def AddComand(self, command: str) -> None: - """[summary] \n - Add a command to the list of the commands. \n - Args: - command (str): [The command to add]. \n - """ - self.__commands.append(command) - - def NormalizeURL(self, url: str) -> str: - """[summary] \n - Normalize the URLs of the git's repositorys of the students, \n - adding the .git at the end if it is not already there. \n - Args: - url (str): [The crudal url of the git's repository]. \n - Returns: - str: [The normalized url]. \n - """ - if ".git" not in url: - url = url.replace('\n', '.git') - return url.replace("\n", "") - - def NormalizeCourse(self, course: str) -> str: - """[summary] \n - Normalize the course name, removing the spaces. \n - Args: - course (str): [The course name]. \n - Returns: - str: [The normalized course name]. \n - """ - return course.replace(' - ', '-').replace(" ", "_") - - def FormatFullnameDate(self, surname: str, name: str) -> str: - """[summary] \n - Format the surname of the student, removing the spaces and replacing them with '_' \n - Args: - surname (str): [The surname of the student]. \n - name (str): [The name of the student]. \n - date (str): [The date of the student]. \n - Returns: - str: [The formatted Fullname like this: surname_name_date]. \n - """ - surname = surname.replace(",", "_").replace(" ", "").replace(" \n", "") - name = name.replace(",", "_").replace(" ", "").replace(" \n", "") - return f'{surname}_{name}_{self.APIDate}' - - def FormatCourse(self, fieldList: str) -> str: - """[summary] \n - Format the course of the student, removing the line jumps and replacing them with '_' \n - Args: - fieldList (str): [The field of the course. It is the second field of the csv file]. \n - Returns: - str: [The formatted course]. \n - """ - return self.NormalizeCourse(fieldList.replace(" \n", "")) - - def MakeCloneCommands(self, dfHandler: DFH) -> None: - """[summary] \n - Make the commands to clone the repositories of the students. \n - Args: - surname (str): [The surname of the student]. \n - course (str): [The course of the student]. \n - git (str): [The url of the git's repository]. \n - """ - for frame in dfHandler.OrderListOfDFStudents: - self.MakeCloneCommandsForDF(frame.reset_index(drop=True), dfHandler) - - def MakeCloneCommandsForDF(self, df: DataFrame, dfHandler: DFH) -> None: - """[summary] \n - Make the commands to clone the repositories of the students. \n - Args: - df (DataFrame): [The DataFrame with the students information]. \n - """ - # *## Deletes the first column [Date] - df = df.drop(columns=dfHandler.ConfigsJsonValues['Date'], inplace=False, axis=1) - df = df.applymap(lambda x: str(x).strip()) - for i in df.index: - crudeCourse = df[dfHandler.ConfigsJsonValues['Course']][i] - courseStr = self.NormalizeCourse(self.FormatCourse(crudeCourse)) - surnameStr = df[dfHandler.ConfigsJsonValues['Surname']][i] - nameStr = df[dfHandler.ConfigsJsonValues['Name']][i] - message = f"Cloning the repository of: {surnameStr}, {nameStr} from {crudeCourse}" - normalizedURL = self.NormalizeURL( - df[dfHandler.ConfigsJsonValues['GitLink']][i]) - normalizedFullname = self.FormatFullnameDate(surnameStr, nameStr) - command = f"git clone {normalizedURL} {self.MainDir}//{courseStr}//{normalizedFullname}" - self.AddComand(command) - self.CloningMessages = message - - def ExecuteCommands(self, cloneMessenger: CM) -> None: - """[summary] \n - Execute the commands to clone the repositories of the students. \n - Args: - commandList (list): [The list of the commands to execute]. \n - """ - commandList = [x.strip() for x in self.Commands] - messages = [x.strip() for x in self.CloningMessages] - - for command in commandList: - cloneMessenger.Message = messages[commandList.index(command)] - cloneMessenger.PrintMessage() - os.system(command) - - def CloneRepositories(self, DfH: DFH, ) -> None: - """[summary] \n - Open the file and get the data. \n - """ - appInfo = f'{self.AppName} - {self.AppVersion} by {self.AppAuthor}' - self.Messenger.Message = appInfo - self.Messenger.PrintMessage() - try: - # ?## Create git Clone commands - self.MakeCloneCommands(DfH) - - # ?## Execute the commands - self.ExecuteCommands(self.Messenger) - - self.Messenger.Message = 'All Repositories have been cloned!' - self.Messenger.PrintMessage() - - except Exception as e: - self.Messenger.Message = f'Exception: {e.args}' - self.Messenger.PrintMessage() - - # ?########? END METHODS ######### diff --git a/Modules/DirectoryManager_Mod/DirManager.py b/Modules/DirectoryManager_Mod/DirManager.py deleted file mode 100644 index 6aee1fe..0000000 --- a/Modules/DirectoryManager_Mod/DirManager.py +++ /dev/null @@ -1,58 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os - - -class DirectoryManager: - """[summary] - Class in charge of create directories. \n - Returns: - class: DirectoryManager - """ - # ?#### START ATTRIBUTES ####? - __dirToCreate: str = '' - # ?#### END ATTRIBUTES ####? - - def __init__(self) ->None: - pass - - @property - def PathToCreate(self)-> str: - """[summary] - Gets the path that need to create if not exist. \n - Returns: - str: [Path to create.] - """ - return self.__dirToCreate - - @PathToCreate.setter - def PathToCreate(self, path: str)->None: - """[summary] - Sets the directory that will create. \n - Args: - path (str): [Directory to create.] - """ - self.__dirToCreate = path - - def createDirIfNoExist(self)->None: - """[summary] - Creates the directory if not exist. \n - """ - if not os.path.exists(self.PathToCreate): - os.makedirs(self.PathToCreate) - diff --git a/Modules/GetData_Mod/DataManager.py b/Modules/GetData_Mod/DataManager.py deleted file mode 100644 index fb27275..0000000 --- a/Modules/GetData_Mod/DataManager.py +++ /dev/null @@ -1,380 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os - -import requests -from Modules.DataFrameHandler_Mod.DFHandler import DataFrameHandler as DFH -from Modules.PrintMessage_Mod.CloneMessenger import CloneMessenger as CM -from pandas import DataFrame - - -class DataManager: - """[summary] \n - Class in charge of the file management to read and process the \n - data of the students in order to clone their repositorys. \n - Returns: - [class]: [DataManager]. \n - """ - # ?########? START ATTRIBUTES ######### - __configAPIURL = '' - __name = '' - __version = '' - __author = '' - __commands: list = [] - __Messenger: CM = CM() - __studentsInfo: DataFrame = DataFrame() - __APIResponse = None - __cloningMessages: list = [] - # ?#######? END ATTRIBUTES ######### - - def __init__(self): - pass - - def InitialConfig(self, name: str, version: str, author: str, APIURL: dict): - """[summary] \n - Initialize the config of the class. \n - Args: - name (str): [The name of the program]. \n - version (str): [The version of the program]. \n - author (str): [The author of the program]. \n - APIURL (dict): [The API URL of the program]. \n - """ - self.SetAppName(name) - self.SetAppVersion(version) - self.AppAuthor = author - self.SetAPIURL(APIURL) - self.APIResponse = self.GetAPIURL() - - # ?########? SETTERS ######### - - def SetFilename(self, fileName: str) -> None: - """[summary] \n - Set the name of the file to read. \n - Args: - fileName (str): [The name of the file to read]. \n - """ - self.fileName = fileName - - def SetAppName(self, name: str) -> None: - """[summary] \n - Set the name of the file. \n - Args: - name (str): [The name of the file]. \n - """ - self.__name = name - - def SetAppVersion(self, version: str) -> None: - """[summary] \n - Set the version of the file. \n - Args: - version (str): [The version of the file]. \n - """ - self.__version = version - - def SetAPIURL(self, api: dict) -> None: - """[summary] \n - Set the URL of the API. \n - Args: \n - api (str): [The URL of the API] \n - "URL": "https://api.github.com/repos", \n - "USER": "CaidevOficial", \n - "REPO": "Python_Udemy_DataManipulation", \n - "BRANCH": "main" \n - Example: "https://api.github.com/repos/CaidevOficial/Python_Udemy_DataManipulation/commits/main". \n - """ - self.__configAPIURL = f'{api["URL"]}/{api["USER"]}/{api["REPO"]}/commits/{api["BRANCH"]}' - - def AddComand(self, command: str) -> None: - """[summary] \n - Add a command to the list of the commands. \n - Args: - command (str): [The command to add]. \n - """ - self.__commands.append(command) - - def SetStudentsDF(self, students: DataFrame) -> None: - """[summary] \n - Sets the dataframe of students to work with. \n - Args: - students (DataFrame): The dataframe of students to work. \n - """ - self.__studentsInfo = students - - # ?#######? GETTERS ######### - - def GetCommands(self) -> list: - """[summary] \n - Get the commands to clone the repositories of the students. \n - Returns: - list: [The list of the commands to execute]. \n - """ - return self.__commands - - def GetAppName(self) -> str: - """[summary] \n - Get the name of the application. \n - Returns: - str: [The name of the application]. \n - """ - return self.__name - - def GetAppVersion(self) -> str: - """[summary] \n - Get the version of the application. \n - Returns: - str: [The version of the application]. \n - """ - return self.__version - - def GetFilename(self) -> str: - """[summary] \n - Get the name of the file. \n - Returns: - str: [The name of the file]. \n - """ - return self.fileName - - def GetAPIURL(self) -> str: - """[summary] \n - Get the URL of the API. \n - Returns: - str: [The URL of the API]. \n - """ - return self.__configAPIURL - - def GetDate(self) -> str: - """[summary] \n - Get the date from the API. \n - Returns: - str: [The date formatted without the dashes]. \n - """ - date = self.APIResponse.json()["commit"]["author"]["date"] - date = date[:10] - return date.replace("-", "") - - def GetStudentsDF(self) -> DataFrame: - """[summary] \n - Gets the Students DataFrame of the class to work with. \n - Returns: - DataFrame: The Actual DataFrame of the students. \n - """ - return self.__studentsInfo - - # ?########? END GETTERS ######### - - # ?########? PROPERTIES ######### - - @property - def AppAuthor(self) -> str: - """[summary] \n - Get the author of the application. \n - Returns: - str: [The author of the application]. \n - """ - return self.__author - - @AppAuthor.setter - def AppAuthor(self, author: str) -> None: - """[summary] \n - Set the author of the application. \n - Args: - author (str): [The author of the application]. \n - """ - self.__author = author - - @property - def Messenger(self) -> CM: - """[summary] \n - Get the Messenger of the class. \n - Returns: - CM: [The Messenger of the class]. \n - """ - return self.__Messenger - - @property - def Commands(self): - """[summary] \n - Get the commands to clone the repositories of the students. \n - Returns: - list: [The list of the commands to execute]. \n - """ - return self.__commands - - @Commands.setter - def Commands(self, commands: list): - """[summary] \n - Set the commands to clone the repositories of the students. \n - Args: - commands (list): [The list of the commands to execute]. \n - """ - self.__commands = commands - - @property - def APIResponse(self) -> str: - """[summary] \n - Get the API Response. \n - Returns: - str: [The API Response]. \n - """ - return self.__APIResponse - - @APIResponse.setter - def APIResponse(self, APILink: str): - """[summary] \n - Set the API Response by sending a request trough the API link. \n - Args: - APILink (str): [The Link of the API]. \n - """ - self.__APIResponse = requests.get(APILink) - - @property - def CloningMessages(self) -> list: - """[summary] \n - Get the list of the cloning messages. \n - Returns: - list: [The list of the cloning messages]. \n - """ - return self.__cloningMessages - - @CloningMessages.setter - def CloningMessages(self, cloningMessage: str): - """[summary] \n - Adds a message to the cloning messages. \n - Args: - cloningMessage (str): [The message to add]. \n - """ - self.__cloningMessages.append(cloningMessage) - - # ?#######? END PROPERTIES ######### - - # ?########? METHODS ######### - - def NormalizeURL(self, url: str) -> str: - """[summary] \n - Normalize the URLs of the git's repositorys of the students, \n - adding the .git at the end if it is not already there. \n - Args: - url (str): [The crudal url of the git's repository]. \n - Returns: - str: [The normalized url]. \n - """ - if not ".git" in url: - url = url.replace(' \n', '') - url = f'{url}.git' - return url.replace("\ \n", "") - - def NormalizeCourse(self, course: str) -> str: - """[summary] \n - Normalize the course name, removing the spaces. \n - Args: - course (str): [The course name]. \n - Returns: - str: [The normalized course name]. \n - """ - return course.replace(' - ', '-').replace(" ", "_") - - def FormatFullnameDate(self, surname: str, name: str) -> str: - """[summary] \n - Format the surname of the student, removing the spaces and replacing them with '_' \n - Args: - surname (str): [The surname of the student]. \n - name (str): [The name of the student]. \n - date (str): [The date of the student]. \n - Returns: - str: [The formatted Fullname like this: surname_name_date]. \n - """ - surname = surname.replace(",", "_").replace(" ", "").replace(" \n", "") - name = name.replace(",", "_").replace(" ", "").replace(" \n", "") - - return f'{surname}_{name}_{self.GetDate()}' - - def FormatCourse(self, fieldList: str) -> str: - """[summary] \n - Format the course of the student, removing the line jumps and replacing them with '_' \n - Args: - fieldList (str): [The field of the course. It is the second field of the csv file]. \n - Returns: - str: [The formatted course]. \n - """ - return self.NormalizeCourse(fieldList.replace(" \n", "")) - - def MakeCloneCommands(self, dfHandler: DFH) -> None: - """[summary] \n - Make the commands to clone the repositories of the students. \n - Args: - surname (str): [The surname of the student]. \n - course (str): [The course of the student]. \n - git (str): [The url of the git's repository]. \n - """ - for frame in dfHandler.OrderListOfDFStudents: - self.MakeCloneCommandsForDF(frame, dfHandler) - - def MakeCloneCommandsForDF(self, df: DataFrame, dfHandler: DFH) -> None: - """[summary] \n - Make the commands to clone the repositories of the students. \n - Args: - df (DataFrame): [The DataFrame with the students information]. \n - """ - for i in df.index: - crudeCourse = df[dfHandler.ConfigsJsonValues['Course']][i] - courseStr = self.NormalizeCourse(self.FormatCourse(crudeCourse)) - surnameStr = df[dfHandler.ConfigsJsonValues['Surname']][i] - nameStr = df[dfHandler.ConfigsJsonValues['Name']][i] - message = f"Cloning {surnameStr}, {nameStr}'s repository from {crudeCourse}" - command = f"git clone {self.NormalizeURL(df[dfHandler.ConfigsJsonValues['GitLink']][i])} {courseStr}//{self.FormatFullnameDate(surnameStr, nameStr)}" - self.AddComand(command) - self.CloningMessages = message - - def ExecuteCommands(self, cloneMessenger: CM) -> None: - """[summary] \n - Execute the commands to clone the repositories of the students. \n - Args: - commandList (list): [The list of the commands to execute]. \n - """ - - commandList = [x.strip() for x in self.Commands] - messages = [x.strip() for x in self.CloningMessages] - - for command in commandList: - cloneMessenger.SetMessage(messages[commandList.index(command)]) - cloneMessenger.PrintMessage() - os.system(command) - - def CloneRepositories(self, DfH: DFH, ) -> None: - """[summary] \n - Open the file and get the data. \n - """ - appInfo = f'{self.GetAppName()} - {self.GetAppVersion()} by {self.AppAuthor}' - self.Messenger.SetMessage(appInfo) - self.Messenger.PrintMessage() - - try: - #? Create git Clone commands - self.MakeCloneCommands(DfH) - - #? Execute the commands - self.ExecuteCommands(self.Messenger) - - self.Messenger.SetMessage('All Repositories have been cloned!') - self.Messenger.PrintMessage() - - except Exception as e: - self.Messenger.SetMessage(f'Exception: {e.args}') - self.Messenger.PrintMessage() - - # ?########? END METHODS ######### diff --git a/Modules/GetData_Mod/__init__.py b/Modules/GetData_Mod/__init__.py deleted file mode 100644 index 89927cb..0000000 --- a/Modules/GetData_Mod/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . diff --git a/Modules/PlotManager_Mod/PlotManager.py b/Modules/PlotManager_Mod/PlotManager.py deleted file mode 100644 index 14be034..0000000 --- a/Modules/PlotManager_Mod/PlotManager.py +++ /dev/null @@ -1,204 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import datetime -import os - -import matplotlib.colors as mcolors -import matplotlib.pyplot as plt -from Modules.DataFrameHandler_Mod.DFHandler import DataFrameHandler - - -class PlotManager: - """[summary] - Class in charge of create the pie chart. \n - Returns: - class: PlotManager - """ - - # ?#### START ATTRIBUTES ####? - __plotDF: DataFrameHandler = None - __labels: list = [] - __slices: list = [] - __colors: list = [] - __title: str = None - __pathToSave: str = None - # ?#### END ATTRIBUTES ####? - - def __init__(self) -> None: - pass - - # ?### START PROPERTIES - GETTERS ###? - - @property - def PathToSave(self) -> str: - """[summary] - Gets the path to save the image of the pie chart. \n - Returns: - str: [The path of the directory to save the image of the pie chart.] - """ - return self.__pathToSave - - @property - def Labels(self) -> list: - """[summary] - Gets the list of labels for the pie chart. \n - Returns: - list: [Labels for the pie Chart] - """ - return self.__labels - - @property - def Slices(self) -> list: - """[summary] - Gets the list of slices with values for every label \n - of the pie chart. \n - Returns: - list: [Slices with values for using in the pie chart] - """ - return self.__slices - - @property - def PlotDF(self) -> DataFrameHandler: - """[summary] - Gets the DataFrameHandler object. \n - Returns: - class: DataFrameHandler - """ - return self.__plotDF - - @property - def Colors(self) -> list: - """[summary] - Gets the list of colors for the pie chart. \n - Returns: - list: [Colors for the pie Chart] - """ - return self.__colors - - @property - def Title(self) -> str: - """[summary] - Gets the title for the legend of the pie chart. \n - Returns: - str: [Title for the legend of the pie chart] - """ - return self.__title - - # ?### END PROPERTIES - GETTERS ###? - - # ?### START PROPERTIES - SETTERS ###? - - @PathToSave.setter - def PathToSave(self, path: str): - """[summary] - Sets the path to save the image of the pie chart. \n - Args: - path (str): [The path of the directory to save the image of the pie chart.] - """ - self.__pathToSave = path.strip() - - @Labels.setter - def Labels(self, value: list): - """[summary] - Sets the list of labels for the pie chart. \n - Args: - value (list): [Labels for using in the pie Chart] - """ - self.__labels = value - - @Slices.setter - def Slices(self, value: list): - """[summary] - Sets the list of slices with values for every label \n - of the pie chart. \n - Args: - value (list): [Slices with values for using in the pie chart] - """ - self.__slices = value - - @PlotDF.setter - def PlotDF(self, value: DataFrameHandler): - """[summary] - Sets the DataFrameHandler object. \n - Args: - value (DataFrameHandler): [DataFrameHandler object] - """ - self.__plotDF = value - - @Colors.setter - def Colors(self, value: list): - """[summary] - Sets the list of colors for the pie chart. \n - Args: - value (list): [Colors for the pie Chart] - """ - self.__colors = value - - @Title.setter - def Title(self, value: str): - """[summary] - Sets the title for the legend of the pie chart. \n - Args: - value (str): [Title for the legend of the pie chart] - """ - self.__title = value.strip() - - # ?### END PROPERTIES - SETTERS ###? - - # ?### START METHODS ###? - - def initialize(self, df: DataFrameHandler, title: str, path: str) -> None: - """[summary] - Initializes the PlotManager object. \n - Args: - df (DataFrameHandler): [DataFrameHandler object] \n - title (str): [Title for the legend of the pie chart] \n - path (str): [Path to save the image of the pie chart] - """ - self.PlotDF = df - self.Labels = self.PlotDF.UniqueColumns - self.Slices = [len(dframe.index) for dframe in self.PlotDF.OrderListOfDFStudents] - self.Title = title - self.PathToSave = path - - def configureRCparams(self) ->None: - """[summary] - Configures the rcParams of the matplotlib. \n - """ - plt.style.use('seaborn-whitegrid') - plt.rcParams['font.family'] = 'Times New Roman' - plt.rcParams['font.size'] = 12 - plt.rcParams['legend.fontsize'] = 8 - plt.rcParams['lines.linewidth'] = 1.5 - plt.rcParams['lines.markersize'] = 5 - plt.rcParams['lines.markeredgewidth'] = 1 - plt.rcParams['figure.figsize'] = (12, 6) - - def createPieChart(self): - """[summary] - Creates the pie chart. \n - """ - self.configureRCparams() - - plt.pie(self.Slices, labels=self.Labels, startangle=45, shadow=True, - autopct='%1.1f%%') - plt.legend(self.Labels, bbox_to_anchor=(1, 0.5), markerscale=1.2, loc='upper left') - plt.title(self.Title) - plt.tight_layout() - plt.savefig(f'{self.PathToSave}/{datetime.datetime.today().strftime("%Y%m%d__%H_%M_%S")}.png', dpi=300) - plt.show() diff --git a/Modules/PrintMessage_Mod/CloneMessenger.py b/Modules/PrintMessage_Mod/CloneMessenger.py deleted file mode 100644 index 35f658b..0000000 --- a/Modules/PrintMessage_Mod/CloneMessenger.py +++ /dev/null @@ -1,84 +0,0 @@ -# GNU General Public License V3 -# -# Copyright (c) 2022 [FacuFalcone] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -class CloneMessenger: - """[summary] - Class to print messages in the console. \n - Returns: - class: [CloneMessenger]. \n - """ - # ?######? START ATTRIBUTES ####### - __message: str = '' - # ?######? END ATTRIBUTES ####### - - def __init__(self) -> None: - pass - - # ?######? START PROPERTIES ####### - - @property - def Message(self) -> str: - """[summary] \n - Get the message of the class. \n - Returns: - str: Message of the class. \n - """ - return self.__message - - @Message.setter - def Message(self, message: str) -> None: - """[summary] \n - Sets the message of the class. \n - Args: - message (str): The message to be printed in the console. \n - """ - self.__message = message - - # ?######? END PROPERTIES ####### - - # ?###########? START METHODS ############ - - def InitializeMessenger(self, message: str) -> None: - """[summary] \n - Initializes the class with a message. \n - Args: - message (str): The message to be printed in the console. \n - """ - self.SetMessage(message) - - def PrintMessage(self) -> None: - """[summary] \n - Creates a string of symbols of the same length of the message and \n - prints them in the console. \n - """ - symbols = self.GenerateSymbols() - print( - ' \n', - f'{symbols} \n', - f'{self.Message} \n', - f'{symbols} \n' - ) - - def GenerateSymbols(self) -> str: - """[summary] \n - Generates a string of symbols of the same length of the message of the class. \n - Returns: - str: String of symbols of the same length of the message of the class. \n - """ - return ''.join(['#' for i in range(len(self.Message))]) - - # ?###########? END METHODS ############ From 799c437386b9c627152b9ce873370686bd1c0dbb Mon Sep 17 00:00:00 2001 From: CaidevOficial Date: Sun, 27 Feb 2022 22:32:54 -0300 Subject: [PATCH 3/3] Update to v2.1.11 --- Modules/DataFrameHandler_Mod/df_handler.py | 265 +++++++++++++ Modules/DataManager_Mod/data_manager.py | 398 ++++++++++++++++++++ Modules/DirectoryManager_Mod/dir_manager.py | 58 +++ Modules/PlotManager_Mod/plot_manager.py | 203 ++++++++++ Modules/PrintMessage_Mod/clone_messenger.py | 88 +++++ github_cloner_2022.py | 105 ++++++ 6 files changed, 1117 insertions(+) create mode 100644 Modules/DataFrameHandler_Mod/df_handler.py create mode 100644 Modules/DataManager_Mod/data_manager.py create mode 100644 Modules/DirectoryManager_Mod/dir_manager.py create mode 100644 Modules/PlotManager_Mod/plot_manager.py create mode 100644 Modules/PrintMessage_Mod/clone_messenger.py create mode 100644 github_cloner_2022.py diff --git a/Modules/DataFrameHandler_Mod/df_handler.py b/Modules/DataFrameHandler_Mod/df_handler.py new file mode 100644 index 0000000..d723196 --- /dev/null +++ b/Modules/DataFrameHandler_Mod/df_handler.py @@ -0,0 +1,265 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from numpy import ndarray +from pandas import DataFrame + + +class DataFrameHandler: + """[summary] \n + Class in charge of configurate and handle all the dataframe operations. \n + Returns: + class: [DataFrameHandler]. \n + """ + # ?####? Attributes ##### + __configs_json_values: dict = {} + __commands = [] + __unique_columns: ndarray = [] + __main_df: DataFrame = None + __students_df = [] + __ordered_list_of_df_students: list = [] + # ?####? End Attributes ##### + + def __init__(self) -> None: + pass + + # ?####? PROPERTIES - Getters ##### + + @property + def OrderListOfDFStudents(self) -> list: + """[summary] \n + Get the list of ordered dataframes. \n + Returns: + [list]: [The list of ordered dataframes]. \n + """ + return self.__ordered_list_of_df_students + + @property + def ConfigsJsonValues(self) -> dict: + """[summary] \n + Get the configs of the json. \n + Returns: + [dict]: [The configs of the json]. \n + """ + return self.__configs_json_values + + @property + def MainDataFrame(self) -> DataFrame: + """[summary] \n + Get the main dataframe. \n + Returns: + [DataFrame]: [The main dataframe]. \n + """ + return self.__main_df + + @property + def UniqueColumns(self) -> ndarray: + """[summary] \n + Get the unique values of the column 'columnValue' [Division]. \n + Returns: + [ndarray]: [The unique values of the column 'columnValue' [Division]]. \n + """ + return self.__unique_columns + + @property + def Commands(self) -> list: + """[summary] \n + Get the list of the commands. \n + Returns: + [list]: [The list of the commands]. \n + """ + return self.__commands + + @property + def StudentsDF(self) -> list: + """[summary] \n + Get the dataframe with the students. \n + Returns: + [DataFrame]: [The dataframe with the students]. \n + """ + return self.__students_df + + # ?####? End PROPERTIES - GETTERS ##### + + # ?####? PROPERTIES - Setters ##### + + @OrderListOfDFStudents.setter + def OrderListOfDFStudents(self, frame: DataFrame) -> None: + """[summary] \n + Set the list of ordered dataframes. \n + Args: + frame (DataFrame): [The ordered dataframes]. \n + """ + self.__ordered_list_of_df_students.append(frame.reset_index(drop=True)) + + @ConfigsJsonValues.setter + def ConfigsJsonValues(self, value: dict) -> None: + """[summary] \n + Set the configs of the json. \n + Args: + value (dict): [The configs of the json]. \n + """ + self.__configs_json_values = value + + @MainDataFrame.setter + def MainDataFrame(self, frame: DataFrame): + """[summary] \n + Set the main dataframe. \n + Args: + frame (DataFrame): [The dataframe to set]. \n + """ + self.__main_df = frame + + @UniqueColumns.setter + def UniqueColumns(self, unique_columns: ndarray): + """[summary] \n + Set the unique values of the column 'columnValue' [Division]. \n + Args: + unique_columns (ndarray): [The unique values of the column 'columnValue' [Division]]. \n + """ + self.__unique_columns = unique_columns + + @Commands.setter + def Commands(self, command: str) -> None: + """[summary] \n + Sets a command inside the list of the commands. \n + Args: + command (str): [The command to add]. \n + """ + self.__commands.append(command) + + @StudentsDF.setter + def StudentsDF(self, frame: DataFrame) -> None: + """[summary] \n + Set the dataframe with the students. \n + Args: + frame (DataFrame): [The dataframe with the students]. \n + """ + self.__students_df.append(frame) + + # ?####? End PROPERTIES - SETTERS ##### + + # ?####? METHODS ##### + + def OrderIndexedDFBy(self, frame: DataFrame, first_field: str, second_field: str, third_field: str) -> DataFrame: + """[summary] \n + Order the dataframe by the specified fields. \n + Args: + frame (DataFrame): [The dataframe to order]. \n + first_field (str): [The first field to order]. \n + second_field (str): [The second field to order]. \n + third_field (str): [The third field to order]. \n + Returns: + [DataFrame]: [The dataframe ordered by the three fields in the specified order]. \n + """ + sorted_df = frame.sort_values( + by=[first_field, second_field, third_field], ascending=[True, True, True]) + return sorted_df + + def GetSpecificStudentsDF(self, frame: DataFrame, column: str, value: str) -> DataFrame: + """[summary] \n + Get the students that have the specified index value in the specified column. \n + The DataFrame MUST be indexed by the 'value' column. \n + Args: + frame (DataFrame): [The dataframe to filter]. \n + column (str): [The column to filter]. \n + value (str): [The value to filter]. \n + Returns: + [DataFrame]: [The dataframe with the filtered students \n + ordered by Course, Surname & Name]. \n + """ + specific_df: DataFrame = frame[frame[column] == value] + ordered_data_frame: DataFrame = self.OrderIndexedDFBy( + specific_df, self.ConfigsJsonValues['Course'], + self.ConfigsJsonValues['Surname'], + self.ConfigsJsonValues['Name'] + ) + return ordered_data_frame + + def CreateListDFStudentsBy(self, frame: DataFrame, column: str, column_value: str): + """[summary] \n + Creates a list of the students that have the specified index \n + value in the specified column. \n + The DataFrame MUST be indexed by the 'value' column. \n + Args: + frame (DataFrame): [The dataframe to filter]. \n + column (str): [The column to filter]. \n + column_value (list): [The values to filter]. \n + """ + self.OrderListOfDFStudents = self.GetSpecificStudentsDF( + frame, column, column_value) + + def ConfigUniqueValuesInColumn(self, column: str): + """[summary] \n + Get the unique values in the specified column and sort them in alphabetical order ASC. \n + Args: + column (str): [The column to filter]. \n + Returns: + [list]: [The unique values in the specified column]. \n + """ + self.UniqueColumns = self.MainDataFrame[column].unique() + self.UniqueColumns.sort() + + def createJSONofDF(self, frame: DataFrame, name: str): + """[summary] \n + Create a json file for the specified dataframe. \n + Args: + frame (DataFrame): [The dataframe to create the json file]. \n + name (str): [The name of the json file]. \n + """ + frame.to_json(f'{name}.json', orient='table', + indent=4, force_ascii=True) + + def createJsonOfEveryDF(self): + """[summary] \n + Create a json file for every dataframe. \n + """ + for students_df in self.OrderListOfDFStudents: + name = students_df.at[students_df.index.values[0], + self.ConfigsJsonValues['Course']] + filename: str = f'{name}.json' + self.createJSONofDF(students_df, filename) + # for i in range(len(self.OrderListOfDFStudents)): + # frame: DataFrame = self.OrderListOfDFStudents[i] + # name = frame.at[frame.index.values[0], + # self.ConfigsJsonValues['Course']] + # filename: str = f'{name}.json' + # self.createJSONofDF(frame, filename) + + # ?####? End METHODS ##### + + # *####* MAIN METHOD ##### + + def ConfigurateDataFrame(self, column_value: str) -> None: + """[summary] \n + Configurate the dataframe with the specified column value. \n + Args: + column_value (str): [The column value to configurate]. \n + """ + + # *# Gets the unique values of the column 'column_value' [Division] + self.ConfigUniqueValuesInColumn(column_value) + # *# For each unique value of the column 'column_value' [Division] + # *# Creates a list of dataframes with the students that have the + # *# specified value in the column 'column_value' [Division] + for unique in self.UniqueColumns: + self.CreateListDFStudentsBy( + self.MainDataFrame, column_value, unique + ) + self.createJsonOfEveryDF() + + # *####* END MAIN METHOD ##### diff --git a/Modules/DataManager_Mod/data_manager.py b/Modules/DataManager_Mod/data_manager.py new file mode 100644 index 0000000..72e5896 --- /dev/null +++ b/Modules/DataManager_Mod/data_manager.py @@ -0,0 +1,398 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import requests + +from Modules.DataFrameHandler_Mod.df_handler import DataFrameHandler as DFH +from Modules.PrintMessage_Mod.clone_messenger import CloneMessenger as CM +from pandas import DataFrame + + +class DataManager: + """[summary] \n + Class in charge of the file management to read and process the \n + data of the students in order to clone their repositorys. \n + Returns: + [class]: [DataManager]. \n + """ + # ?########? START ATTRIBUTES ######### + __mainDir: str = '' + __configAPIURL = '' + __APIResponse = None + __APIDate = None + __name = '' + __version = '' + __author = '' + __studentsInfo: DataFrame = DataFrame() + __commands: list = [] + __Messenger: CM = CM() + __cloningMessages: list = [] + # ?#######? END ATTRIBUTES ######### + + def __init__(self): + pass + + # ?########? PROPERTIES - GET ######### + + @property + def AppAuthor(self) -> str: + """[summary] \n + Get the author of the application. \n + Returns: + str: [The author of the application]. \n + """ + return self.__author + + @property + def Messenger(self) -> CM: + """[summary] \n + Get the Messenger of the class. \n + Returns: + CM: [The Messenger of the class]. \n + """ + return self.__Messenger + + @property + def Commands(self): + """[summary] \n + Get the commands to clone the repositories of the students. \n + Returns: + list: [The list of the commands to execute]. \n + """ + return self.__commands + + @property + def APIResponse(self) -> str: + """[summary] \n + Get the API Response. \n + Returns: + str: [The API Response]. \n + """ + return self.__APIResponse + + @property + def AppName(self) -> str: + """[summary] \n + Set the name of the file. \n + Args: + name (str): [The name of the file]. \n + """ + return self.__name + + @property + def AppVersion(self) -> str: + """[summary] \n + Get the version of the application. \n + Returns: + str: [The version of the application]. \n + """ + return self.__version + + @property + def APIURL(self) -> str: + """[summary] \n + Get the URL of the API. \n + Returns: + str: [The URL of the API]. \n + """ + return self.__configAPIURL + + @property + def StudensDF(self) -> DataFrame: + """[summary] \n + Get the dataframe with the students information. \n + Returns: + DataFrame: [The dataframe with the students information]. \n + """ + return self.__studentsInfo + + @property + def CloningMessages(self) -> list: + """[summary] \n + Get the list of the cloning messages. \n + Returns: + list: [The list of the cloning messages]. \n + """ + return self.__cloningMessages + + @property + def APIDate(self) -> str: + """[summary] \n + Get the date of the API. \n + Returns: + str: [The date of the API]. \n + """ + return self.__APIDate + + @property + def MainDir(self) -> str: + """[summary] \n + Get the main directory to save the downloaded repositories. \n + Returns: + str: [The main directory to save the downloaded repositories]. \n + """ + return self.__mainDir + + # ?########? END PROPERTIES - GET ######### + + # ?########? START PROPERTIES - SET ######### + + @AppAuthor.setter + def AppAuthor(self, author: str) -> None: + """[summary] \n + Set the author of the application. \n + Args: + author (str): [The author of the application]. \n + """ + self.__author = author + + @Commands.setter + def Commands(self, commands: list): + """[summary] \n + Set the commands to clone the repositories of the students. \n + Args: + commands (list): [The list of the commands to execute]. \n + """ + self.__commands = commands + + @APIResponse.setter + def APIResponse(self, APILink: str): + """[summary] \n + Set the API Response by sending a request trough the API link. \n + Args: + APILink (str): [The Link of the API]. \n + """ + self.__APIResponse = requests.get(APILink) + + @AppName.setter + def AppName(self, name: str) -> None: + """[summary] \n + Set the name of the file. \n + Args: + name (str): [The name of the file]. \n + """ + self.__name = name + + @AppVersion.setter + def AppVersion(self, version: str) -> None: + """[summary] \n + Set the version of the file. \n + Args: + version (str): [The version of the file]. \n + """ + self.__version = version + + @APIURL.setter + def APIURL(self, url: dict) -> None: + """[summary] \n + Set the URL of the API. \n + Args: \n + url (dict): [The json with all the fields of the API url.] \n + "URL": "https://api.github.com/repos", \n + "USER": "Your_Github_User", \n + "REPO": "Your_Repository", \n + "BRANCH": "Your_Principal_Branch" \n + Example: "https://api.github.com/repos/Your_Github_User/Your_Repository/commits/Your_Principal_Branch". \n + """ + self.__configAPIURL = f'{url["URL"]}/{url["USER"]}/{url["REPO"]}/commits/{url["BRANCH"]}' + + @StudensDF.setter + def StudensDF(self, studentsInfo: DataFrame) -> None: + """[summary] \n + Set the dataframe of students to work with. \n + Args: + studentsInfo (DataFrame): The dataframe of students to work. \n + """ + self.__studentsInfo = studentsInfo + + @CloningMessages.setter + def CloningMessages(self, cloningMessage: str): + """[summary] \n + Adds a message to the cloning messages. \n + Args: + cloningMessage (str): [The message to add]. \n + """ + self.__cloningMessages.append(cloningMessage) + + @APIDate.setter + def APIDate(self, APIResponse: str): + """[summary] \n + Set the date of the API. \n + Args: + APIResponse (str): [The response of the API Setted]. \n + """ + date = APIResponse.json()["commit"]["author"]["date"] + date = date[:10] + self.__APIDate = date.replace("-", "") + + @MainDir.setter + def MainDir(self, mainDir: str) -> None: + """[summary] \n + Set the main directory to save the downloaded repositories. \n + Args: + mainDir (str): [The main directory to save the downloaded repositories]. \n + """ + self.__mainDir = mainDir.strip() + + # ?#######? END PROPERTIES - SET ######### + + # ?########? METHODS ######### + + def InitialConfig(self, name: str, version: str, author: str, APIURL: dict, mainDir: str): + """[summary] \n + Initialize the config of the class, Also sets the API response \n + and the date of the API. \n + Args: + name (str): [The name of the program]. \n + version (str): [The version of the program]. \n + author (str): [The author of the program]. \n + APIURL (dict): [The API URL of the program]. \n + mainDir (str): [The main directory to clone repositories]. \n + """ + self.AppName = name + self.AppVersion = version + self.AppAuthor = author + self.APIURL = APIURL + self.APIResponse = self.APIURL + self.APIDate = self.APIResponse + self.MainDir = mainDir + + def AddComand(self, command: str) -> None: + """[summary] \n + Add a command to the list of the commands. \n + Args: + command (str): [The command to add]. \n + """ + self.__commands.append(command) + + def NormalizeURL(self, url: str) -> str: + """[summary] \n + Normalize the URLs of the git's repositorys of the students, \n + adding the .git at the end if it is not already there. \n + Args: + url (str): [The crudal url of the git's repository]. \n + Returns: + str: [The normalized url]. \n + """ + if ".git" not in url: + url = url.replace('\n', '.git') + return url.replace("\n", "") + + def NormalizeCourse(self, course: str) -> str: + """[summary] \n + Normalize the course name, removing the spaces. \n + Args: + course (str): [The course name]. \n + Returns: + str: [The normalized course name]. \n + """ + return course.replace(' - ', '-').replace(" ", "_") + + def FormatFullnameDate(self, surname: str, name: str) -> str: + """[summary] \n + Format the surname of the student, removing the spaces and replacing them with '_' \n + Args: + surname (str): [The surname of the student]. \n + name (str): [The name of the student]. \n + date (str): [The date of the student]. \n + Returns: + str: [The formatted Fullname like this: surname_name_date]. \n + """ + surname = surname.replace(",", "_").replace(" ", "").replace(" \n", "") + name = name.replace(",", "_").replace(" ", "").replace(" \n", "") + return f'{surname}_{name}_{self.APIDate}' + + def FormatCourse(self, fieldList: str) -> str: + """[summary] \n + Format the course of the student, removing the line jumps and replacing them with '_' \n + Args: + fieldList (str): [The field of the course. It is the second field of the csv file]. \n + Returns: + str: [The formatted course]. \n + """ + return self.NormalizeCourse(fieldList.replace(" \n", "")) + + def MakeCloneCommands(self, dfHandler: DFH) -> None: + """[summary] \n + Make the commands to clone the repositories of the students. \n + Args: + surname (str): [The surname of the student]. \n + course (str): [The course of the student]. \n + git (str): [The url of the git's repository]. \n + """ + for frame in dfHandler.OrderListOfDFStudents: + self.MakeCloneCommandsForDF(frame, dfHandler) + + def MakeCloneCommandsForDF(self, df: DataFrame, dfHandler: DFH) -> None: + """[summary] \n + Make the commands to clone the repositories of the students. \n + Args: + df (DataFrame): [The DataFrame with the students information]. \n + """ + # *## Deletes the first column [Date] + df = df.drop(columns=dfHandler.ConfigsJsonValues['Date'], inplace=False, axis=1) + df = df.applymap(lambda x: str(x).strip()) + for i in df.index: + crudeCourse = df[dfHandler.ConfigsJsonValues['Course']][i] + courseStr = self.NormalizeCourse(self.FormatCourse(crudeCourse)) + surnameStr = df[dfHandler.ConfigsJsonValues['Surname']][i] + nameStr = df[dfHandler.ConfigsJsonValues['Name']][i] + message = f"Cloning the repository of: {surnameStr}, {nameStr} from {crudeCourse}" + normalizedURL = self.NormalizeURL( + df[dfHandler.ConfigsJsonValues['GitLink']][i]) + normalizedFullname = self.FormatFullnameDate(surnameStr, nameStr) + command = f"git clone {normalizedURL} {self.MainDir}//{courseStr}//{normalizedFullname}" + self.AddComand(command) + self.CloningMessages = message + + def ExecuteCommands(self, cloneMessenger: CM) -> None: + """[summary] \n + Execute the commands to clone the repositories of the students. \n + Args: + commandList (list): [The list of the commands to execute]. \n + """ + commandList = [x.strip() for x in self.Commands] + messages = [x.strip() for x in self.CloningMessages] + + for command in commandList: + cloneMessenger.Message = messages[commandList.index(command)] + cloneMessenger.PrintMessage() + os.system(command) + + def CloneRepositories(self, DfH: DFH, ) -> None: + """[summary] \n + Open the file and get the data. \n + """ + appInfo = f'{self.AppName} - {self.AppVersion} by {self.AppAuthor}' + self.Messenger.Message = appInfo + self.Messenger.PrintMessage() + try: + # ?## Create git Clone commands + self.MakeCloneCommands(DfH) + + # ?## Execute the commands + self.ExecuteCommands(self.Messenger) + + self.Messenger.Message = 'All Repositories have been cloned!' + self.Messenger.PrintMessage() + + except Exception as e: + self.Messenger.Message = f'Exception: {e.args}' + self.Messenger.PrintMessage() + + # ?########? END METHODS ######### diff --git a/Modules/DirectoryManager_Mod/dir_manager.py b/Modules/DirectoryManager_Mod/dir_manager.py new file mode 100644 index 0000000..6aee1fe --- /dev/null +++ b/Modules/DirectoryManager_Mod/dir_manager.py @@ -0,0 +1,58 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os + + +class DirectoryManager: + """[summary] + Class in charge of create directories. \n + Returns: + class: DirectoryManager + """ + # ?#### START ATTRIBUTES ####? + __dirToCreate: str = '' + # ?#### END ATTRIBUTES ####? + + def __init__(self) ->None: + pass + + @property + def PathToCreate(self)-> str: + """[summary] + Gets the path that need to create if not exist. \n + Returns: + str: [Path to create.] + """ + return self.__dirToCreate + + @PathToCreate.setter + def PathToCreate(self, path: str)->None: + """[summary] + Sets the directory that will create. \n + Args: + path (str): [Directory to create.] + """ + self.__dirToCreate = path + + def createDirIfNoExist(self)->None: + """[summary] + Creates the directory if not exist. \n + """ + if not os.path.exists(self.PathToCreate): + os.makedirs(self.PathToCreate) + diff --git a/Modules/PlotManager_Mod/plot_manager.py b/Modules/PlotManager_Mod/plot_manager.py new file mode 100644 index 0000000..80678af --- /dev/null +++ b/Modules/PlotManager_Mod/plot_manager.py @@ -0,0 +1,203 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import datetime + +import matplotlib.colors as mcolors +import matplotlib.pyplot as plt +from Modules.DataFrameHandler_Mod.df_handler import DataFrameHandler + + +class PlotManager: + """[summary] + Class in charge of create the pie chart. \n + Returns: + class: PlotManager + """ + + # ?#### START ATTRIBUTES ####? + __plotDF: DataFrameHandler = None + __labels: list = [] + __slices: list = [] + __colors: list = [] + __title: str = None + __pathToSave: str = None + # ?#### END ATTRIBUTES ####? + + def __init__(self) -> None: + pass + + # ?### START PROPERTIES - GETTERS ###? + + @property + def PathToSave(self) -> str: + """[summary] + Gets the path to save the image of the pie chart. \n + Returns: + str: [The path of the directory to save the image of the pie chart.] + """ + return self.__pathToSave + + @property + def Labels(self) -> list: + """[summary] + Gets the list of labels for the pie chart. \n + Returns: + list: [Labels for the pie Chart] + """ + return self.__labels + + @property + def Slices(self) -> list: + """[summary] + Gets the list of slices with values for every label \n + of the pie chart. \n + Returns: + list: [Slices with values for using in the pie chart] + """ + return self.__slices + + @property + def PlotDF(self) -> DataFrameHandler: + """[summary] + Gets the DataFrameHandler object. \n + Returns: + class: DataFrameHandler + """ + return self.__plotDF + + @property + def Colors(self) -> list: + """[summary] + Gets the list of colors for the pie chart. \n + Returns: + list: [Colors for the pie Chart] + """ + return self.__colors + + @property + def Title(self) -> str: + """[summary] + Gets the title for the legend of the pie chart. \n + Returns: + str: [Title for the legend of the pie chart] + """ + return self.__title + + # ?### END PROPERTIES - GETTERS ###? + + # ?### START PROPERTIES - SETTERS ###? + + @PathToSave.setter + def PathToSave(self, path: str): + """[summary] + Sets the path to save the image of the pie chart. \n + Args: + path (str): [The path of the directory to save the image of the pie chart.] + """ + self.__pathToSave = path.strip() + + @Labels.setter + def Labels(self, value: list): + """[summary] + Sets the list of labels for the pie chart. \n + Args: + value (list): [Labels for using in the pie Chart] + """ + self.__labels = value + + @Slices.setter + def Slices(self, value: list): + """[summary] + Sets the list of slices with values for every label \n + of the pie chart. \n + Args: + value (list): [Slices with values for using in the pie chart] + """ + self.__slices = value + + @PlotDF.setter + def PlotDF(self, value: DataFrameHandler): + """[summary] + Sets the DataFrameHandler object. \n + Args: + value (DataFrameHandler): [DataFrameHandler object] + """ + self.__plotDF = value + + @Colors.setter + def Colors(self, value: list): + """[summary] + Sets the list of colors for the pie chart. \n + Args: + value (list): [Colors for the pie Chart] + """ + self.__colors = value + + @Title.setter + def Title(self, value: str): + """[summary] + Sets the title for the legend of the pie chart. \n + Args: + value (str): [Title for the legend of the pie chart] + """ + self.__title = value.strip() + + # ?### END PROPERTIES - SETTERS ###? + + # ?### START METHODS ###? + + def initialize(self, df: DataFrameHandler, title: str, path: str) -> None: + """[summary] + Initializes the PlotManager object. \n + Args: + df (DataFrameHandler): [DataFrameHandler object] \n + title (str): [Title for the legend of the pie chart] \n + path (str): [Path to save the image of the pie chart] + """ + self.PlotDF = df + self.Labels = self.PlotDF.UniqueColumns + self.Slices = [len(dframe.index) for dframe in self.PlotDF.OrderListOfDFStudents] + self.Title = title + self.PathToSave = path + + def configureRCparams(self) ->None: + """[summary] + Configures the rcParams of the matplotlib. \n + """ + plt.style.use('seaborn-whitegrid') + plt.rcParams['font.family'] = 'Times New Roman' + plt.rcParams['font.size'] = 12 + plt.rcParams['legend.fontsize'] = 8 + plt.rcParams['lines.linewidth'] = 1.5 + plt.rcParams['lines.markersize'] = 5 + plt.rcParams['lines.markeredgewidth'] = 1 + plt.rcParams['figure.figsize'] = (12, 6) + + def createPieChart(self): + """[summary] + Creates the pie chart. \n + """ + self.configureRCparams() + + plt.pie(self.Slices, labels=self.Labels, startangle=45, shadow=True, + autopct='%1.1f%%') + plt.legend(self.Labels, bbox_to_anchor=(1, 0.5), markerscale=1.2, loc='upper left') + plt.title(self.Title) + plt.tight_layout() + plt.savefig(f'{self.PathToSave}/{datetime.datetime.today().strftime("%Y%m%d__%H_%M_%S")}.png', dpi=300) + plt.show() diff --git a/Modules/PrintMessage_Mod/clone_messenger.py b/Modules/PrintMessage_Mod/clone_messenger.py new file mode 100644 index 0000000..d7081bd --- /dev/null +++ b/Modules/PrintMessage_Mod/clone_messenger.py @@ -0,0 +1,88 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +class CloneMessenger: + """[summary] + Class to print messages in the console. \n + Returns: + class: [CloneMessenger]. \n + """ + # ?######? START ATTRIBUTES ####### + __message: str = '' + # ?######? END ATTRIBUTES ####### + + def __init__(self) -> None: + pass + + # ?######? START PROPERTIES ####### + + @property + def Message(self) -> str: + """[summary] \n + Get the message of the class. \n + Returns: + str: Message of the class. \n + """ + return self.__message + + @Message.setter + def Message(self, message: str) -> None: + """[summary] \n + Sets the message of the class. \n + Args: + message (str): The message to be printed in the console. \n + """ + self.__message = message + + # ?######? END PROPERTIES ####### + + # ?###########? START METHODS ############ + + def InitializeMessenger(self, message: str) -> None: + """[summary] \n + Initializes the class with a message. \n + Args: + message (str): The message to be printed in the console. \n + """ + self.SetMessage(message) + + def PrintMessage(self) -> None: + """[summary] \n + Creates a string of symbols of the same length of the message and \n + prints them in the console. \n + like: \n + ############### \n + ##Your Message ## \n + ############### \n + """ + symbols = self.GenerateSymbols() + print( + ' \n', + f'{symbols} \n', + f'{self.Message} \n', + f'{symbols} \n' + ) + + def GenerateSymbols(self) -> str: + """[summary] \n + Generates a string of symbols of the same length of the message of the class. \n + Returns: + str: String of symbols of the same length of the message of the class. \n + """ + return ''.join(['#' for i in range(len(self.Message))]) + + # ?###########? END METHODS ############ diff --git a/github_cloner_2022.py b/github_cloner_2022.py new file mode 100644 index 0000000..404a960 --- /dev/null +++ b/github_cloner_2022.py @@ -0,0 +1,105 @@ +# GNU General Public License V3 +# +# Copyright (c) 2022 [FacuFalcone] +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import datetime +import pandas as pd + +from Modules.DataFrameHandler_Mod.df_handler import DataFrameHandler as DfH +from Modules.DataManager_Mod.data_manager import DataManager as DM +from Modules.DirectoryManager_Mod.dir_manager import DirectoryManager as DirM +from Modules.Formatter_Mod.formatter import Formatter as FMT +from Modules.PlotManager_Mod.plot_manager import PlotManager as Plot +from Modules.PrintMessage_Mod.clone_messenger import CloneMessenger as CM + +# ?######### Start Basic Configuration ########## +FILENAME = 'Github_Repositories.csv' +NAME = 'Github Repository Cloner' +VERSION = '[V2.1.11]' +AUTHOR = '[FacuFalcone - CaidevOficial]' +FILE_CONFIG_NAME = 'Modules/API_Info.json' +# ?######### End Basic Configuration ########## + +if __name__ == '__main__': + try: + start_time = datetime.datetime.now() + # ?#########? Start Initialization ########## + JsonFile = pd.read_json(f"./{FILE_CONFIG_NAME}", orient='records') + JsonAPI = JsonFile['Github'] + JsonDFConfigs = JsonFile['DataFrame']['Fields'] + JsonDirConfigs = JsonFile['Files'] + # ?#########? End Initialization ############ + + # ?#########? Start Objects Instances ########## + Handler = DfH() + Manager = DM() + Messenger = CM() + Timer = FMT() + Plotter = Plot() + DirManager = DirM() + # ?#########? End Objects Instances ########## + + # ?#########? Start Directory Creation ########## + DirManager.PathToCreate = JsonDirConfigs['Dir_Plots_img'] + DirManager.createDirIfNoExist() + + DirManager.PathToCreate = JsonDirConfigs['Dir_Cloned_Repos'] + DirManager.createDirIfNoExist() + # ?#########? End Directory Creation ########## + + # ?#########? Start DataManager Configuration ########## + Manager.InitialConfig(NAME, VERSION, AUTHOR, JsonAPI, JsonDirConfigs['Dir_Cloned_Repos']) + # ?#########? End DataManager Configuration ########## + + # ?#########? Start DataFrame Configuration ########## + # *# Reads the 'csv' File to get the dataframe + df = pd.read_csv(FILENAME) + + # *# Sets the Main DF to the class to handle it + Handler.MainDataFrame = df + Handler.ConfigsJsonValues = JsonDFConfigs + Handler.ConfigurateDataFrame(Handler.ConfigsJsonValues['Course']) + # ?#########? End DataFrame Configuration ########## + + # ?#########? Start Initialize DataManager ########## + Manager.CloneRepositories(Handler) + # ?##########? End Initialize DataManager ########### + + # ?#########? Start PlotManager Configuration ########## + Plotter.initialize(Handler, 'Repositories to Clone', JsonDirConfigs['Dir_Plots_img']) + + # ?#########? Start Timer Config ########## + Timer.CrudeTime = start_time + # ?#########? End Timer Config ########## + + # ?#########? Start Print Message ########## + Messenger.Message = f"Elapsed Time: {Timer.FormattedTimeStr}" + Messenger.PrintMessage() + + Messenger.Message = f"Thanks for using {NAME} {VERSION} by {AUTHOR}! ♥" + Messenger.PrintMessage() + + Messenger.Message = "Creating Pie Chart..." + Messenger.PrintMessage() + Plotter.createPieChart() + + Messenger.Message = "Success! All task done. Press a key to close the app" + Messenger.PrintMessage() + # ?#########? End Print Message ########## + except Exception as e: + print(f'Exception: {e.args}') + finally: + end = input()