diff --git a/GithubCloner2022.py b/GithubCloner2022.py
index 0e519bc..e3c9115 100644
--- a/GithubCloner2022.py
+++ b/GithubCloner2022.py
@@ -15,48 +15,73 @@
# 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.GetData_Mod.DataManager import DataManager as DM
+from Modules.DataManager_Mod.DataManager import DataManager as DM
+from Modules.Formatter_Mod.Formatter import Formatter as FMT
+from Modules.PrintMessage_Mod.CloneMessenger import CloneMessenger as CM
+
# ?######### Start Basic Configuration ##########
filename = 'Github_Repositories.csv'
name = 'Github Repository Cloner'
-version = '[V2.0.11]'
+version = '[V2.0.12]'
author = '[FacuFalcone - CaidevOficial]'
fileConfigName = 'Modules/API_Info.json'
# ?######### End Basic Configuration ##########
-try:
- # ?#########? Start Initialization ##########
- JsonFile = pd.read_json(f"./{fileConfigName}", orient='records')
- JsonAPI = JsonFile['Github']
- JsonDFConfigs = JsonFile['DataFrame']['Fields']
- # ?#########? End Initialization ############
-
- # ?#########? Start Objects Instances ##########
- Handler = DfH()
- Manager = DM()
- # ?#########? End Objects Instances ##########
-
- # ?#########? Start DataManager Configuration ##########
- Manager.InitialConfig(name, version, author, JsonAPI)
- # ?#########? 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 ###########
-
-except Exception as e:
- print(f'Exception: {e.args}')
+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']
+ # ?#########? End Initialization ############
+
+ # ?#########? Start Objects Instances ##########
+ Handler = DfH()
+ Manager = DM()
+ Messenger = CM()
+ Timer = FMT()
+ # ?#########? End Objects Instances ##########
+
+ # ?#########? Start DataManager Configuration ##########
+ Manager.InitialConfig(name, version, author, JsonAPI)
+ # ?#########? 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 ###########
+ 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 = "Success! All task done. Press a key to close the app"
+ Messenger.PrintMessage()
+ # ?#########? End Print Message ##########
+
+ end = input()
diff --git a/Github_Repositories.csv b/Github_Repositories.csv
index ce50003..dee755d 100644
--- a/Github_Repositories.csv
+++ b/Github_Repositories.csv
@@ -1,7 +1,12 @@
"Marca temporal","Nombre/s","Apellido/s","División","DNI / Legajo","E-Mail","Link al repositorio"
-"2022/02/13 10:26:52 p. m. GMT-3","Neptune","Romane God","1G - Professor 1 - Helper 1","222222","neptune@notplanet.com","https://github.com/caidevOficial/SPD2022_TPS.git"
-"2022/02/13 10:26:52 p. m. GMT-3","Poseidon","Grecian God","1F - Professor 2 - Helper 2","333333","poseidon@sea.com","https://github.com/caidevOficial/Python_ITBA_IEEE.git"
+"2022/02/13 10:26:52 p. m. GMT-3","Neptune","Romane God","1G - Professor 1 - Helper 1","222222","neptune@notplanet.com","https://github.com/caidevOficial/Python_RepositoryCloner"
+"2022/02/13 10:26:52 p. m. GMT-3","Poseidon","Grecian God","1F - Professor 2 - Helper 2","333333","poseidon@sea.com","https://github.com/caidevOficial/Python_ITBA_IEEE"
"2022/02/13 10:26:52 p. m. GMT-3","Hades","Grecian God","1F - Professor 2 - Helper 2","111111","Hades@underworld.com","https://github.com/caidevOficial/CaidevOficial.git"
-"2022/02/13 10:26:52 p. m. GMT-3","Zeus","Grecian God","1G - Professor 1 - Helper 1","444444","zeus@ray.com","https://github.com/caidevOficial/Python_IEEE_Team14293.git"
+"2022/02/13 10:26:52 p. m. GMT-3","Zeus","Grecian God","1G - Professor 1 - Helper 1","444444","zeus@ray.com","https://github.com/caidevOficial/Python_RepositoryCloner.git"
"2022/02/13 10:26:52 p. m. GMT-3","Mercury","Romane God","1G - Professor 1 - Helper 1","222222","neptune@notplanet.com","https://github.com/caidevOficial/SPD2022_TPS.git"
"2022/02/13 10:26:52 p. m. GMT-3","Artemisa","Grecian God","1G - Professor 1 - Helper 1","444444","zeus@ray.com","https://github.com/caidevOficial/Python_IEEE_Team14293.git"
+"2022/02/13 10:26:52 p. m. GMT-3","Helios","Romane God","1F - Professor 2 - Helper 2","555555","Helios@notsun.com","https://github.com/caidevOficial/Python_RepositoryCloner"
+"2022/02/13 10:26:52 p. m. GMT-3","Odin","Nordic God","1G - Professor 1 - Helper 1","777777","odin@fatherofall.com","https://github.com/caidevOficial/Python_RepositoryCloner.git"
+"2022/02/13 10:26:52 p. m. GMT-3","Thor","Nordic God","1F - Professor 2 - Helper 2","888888","thor@thundergod.com","https://github.com/caidevOficial/Python_RepositoryCloner"
+"2022/02/13 10:26:52 p. m. GMT-3","Loki","Nordic God","1G - Professor 1 - Helper 1","888888","loki@trapgod.com","https://github.com/caidevOficial/Python_RepositoryCloner"
+"2022/02/13 10:26:52 p. m. GMT-3","Valhalla","Nordic Reign","1F - Professor 2 - Helper 2","999999","valhalla@nordicreign.com","https://github.com/caidevOficial/Python_RepositoryCloner"
diff --git a/Media/FinalMessage.png b/Media/FinalMessage.png
new file mode 100644
index 0000000..5f602d6
Binary files /dev/null and b/Media/FinalMessage.png differ
diff --git a/Modules/API_Info.json b/Modules/API_Info.json
index 8b92de3..a14c202 100644
--- a/Modules/API_Info.json
+++ b/Modules/API_Info.json
@@ -2,7 +2,7 @@
"Github": {
"URL": "https://api.github.com/repos",
"USER": "CaidevOficial",
- "REPO": "Python_Udemy_DataManipulation",
+ "REPO": "Python_RepositoryCloner",
"BRANCH": "main"
},
"DataFrame": {
diff --git a/Modules/DataFrameHandler_Mod/DFHandler.py b/Modules/DataFrameHandler_Mod/DFHandler.py
index 47c6154..5fd36c6 100644
--- a/Modules/DataFrameHandler_Mod/DFHandler.py
+++ b/Modules/DataFrameHandler_Mod/DFHandler.py
@@ -232,10 +232,11 @@ def ConfigurateDataFrame(self, columnValue: str) -> None:
columnValue (str): [The column value to configurate]. \n
"""
- #* Gets the unique values of the column 'columnValue' [Division]
+ # *# 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 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)
diff --git a/Modules/DataFrameHandler_Mod/__init__.py b/Modules/DataFrameHandler_Mod/__init__.py
index 89927cb..7d112a3 100644
--- a/Modules/DataFrameHandler_Mod/__init__.py
+++ b/Modules/DataFrameHandler_Mod/__init__.py
@@ -1,16 +1,16 @@
# 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/DataManager_Mod/DataManager.py b/Modules/DataManager_Mod/DataManager.py
new file mode 100644
index 0000000..cf69766
--- /dev/null
+++ b/Modules/DataManager_Mod/DataManager.py
@@ -0,0 +1,374 @@
+# 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 = ''
+ __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
+
+ # ?########? 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("-", "")
+
+ # ?#######? END PROPERTIES - SET #########
+
+ # ?########? METHODS #########
+
+ def InitialConfig(self, name: str, version: str, author: str, APIURL: dict):
+ """[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
+ """
+ self.AppName = name
+ self.AppVersion = version
+ self.AppAuthor = author
+ self.APIURL = APIURL
+ self.APIResponse = self.APIURL
+ self.APIDate = self.APIResponse
+
+ 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
+ """
+ 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} {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/DataManager_Mod/__init__.py b/Modules/DataManager_Mod/__init__.py
new file mode 100644
index 0000000..7d112a3
--- /dev/null
+++ b/Modules/DataManager_Mod/__init__.py
@@ -0,0 +1,16 @@
+# 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/Formatter_Mod/Formatter.py b/Modules/Formatter_Mod/Formatter.py
new file mode 100644
index 0000000..b0a5574
--- /dev/null
+++ b/Modules/Formatter_Mod/Formatter.py
@@ -0,0 +1,85 @@
+# 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
+
+
+class Formatter:
+ """[summary] \n
+ Formats the time saved in the attribute of the class, as a string. \n
+ like: {:02.0f} minute(s) {:02.0f} seconds. \n
+ Returns:
+ class: [Formatter]. \n
+ """
+
+ # ?###########? START ATTRIBUTES ############
+ __crudeTime = None
+ __formattedTimeStr: str = ''
+ # ?###########? END ATTRIBUTES ############
+
+ def __init__(self) -> None:
+ pass
+
+ # ?######? START PROPERTIES #######
+
+ @property
+ def CrudeTime(self) -> datetime:
+ return self.__crudeTime
+
+ @property
+ def FormattedTimeStr(self) -> str:
+ """[summary] \n
+ Gets the formatted time string.
+ Returns:
+ str: [The formatted time string.]
+ """
+ return self.__formattedTimeStr
+
+ @CrudeTime.setter
+ def CrudeTime(self, value: datetime) -> None:
+ """[summary] \n
+ Sets the time into the class and format it as a string like: \n
+ {:02.0f} minute(s) {:02.0f} seconds. \n
+ Args:
+ value (datetime): [Time to be formatted and saved into the class.]
+ """
+ self.__crudeTime = value
+ self.__FormatDatetimeAsString()
+
+ @FormattedTimeStr.setter
+ def FormattedTimeStr(self, formatTime: str) -> None:
+ """[summary] \n
+ Sets the formatted time as a string.
+ Args:
+ start_time (datetime): [Formatted Time] \n
+ """
+ self.__formattedTimeStr = formatTime
+
+ # ?###########? END PROPERTIES ############
+
+ # ?###########? START METHODS ############
+
+ def __FormatDatetimeAsString(self) -> None:
+ """[summary] \n
+ Formats the time saved in the attribute of the class, as a string. \n
+ like: {:02.0f} minute(s) {:02.0f} seconds. \n
+ """
+ seconds = (datetime.datetime.now() - self.CrudeTime).total_seconds()
+ m, s = divmod(seconds, 60)
+ self.FormattedTimeStr = "{:02.0f} minute(s) {:02.0f} seconds".format(m, s)
+
+ # ?###########? END METHODS ############
diff --git a/Modules/Formatter_Mod/__init__.py b/Modules/Formatter_Mod/__init__.py
new file mode 100644
index 0000000..7d112a3
--- /dev/null
+++ b/Modules/Formatter_Mod/__init__.py
@@ -0,0 +1,16 @@
+# 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/PrintMessage_Mod/CloneMessenger.py b/Modules/PrintMessage_Mod/CloneMessenger.py
index e3f12dd..35f658b 100644
--- a/Modules/PrintMessage_Mod/CloneMessenger.py
+++ b/Modules/PrintMessage_Mod/CloneMessenger.py
@@ -28,7 +28,19 @@ class CloneMessenger:
def __init__(self) -> None:
pass
- def SetMessage(self, message: str) -> None:
+ # ?######? 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:
@@ -36,13 +48,7 @@ def SetMessage(self, message: str) -> None:
"""
self.__message = message
- def GetMessage(self) -> str:
- """[summary] \n
- Gets the message of the class. \n
- Returns:
- str: Message of the class to be printed in the console. \n
- """
- return self.__message
+ # ?######? END PROPERTIES #######
# ?###########? START METHODS ############
@@ -63,7 +69,7 @@ def PrintMessage(self) -> None:
print(
' \n',
f'{symbols} \n',
- f'{self.GetMessage()} \n',
+ f'{self.Message} \n',
f'{symbols} \n'
)
@@ -73,6 +79,6 @@ def GenerateSymbols(self) -> str:
Returns:
str: String of symbols of the same length of the message of the class. \n
"""
- return ''.join(['#' for i in range(len(self.GetMessage()))])
+ return ''.join(['#' for i in range(len(self.Message))])
# ?###########? END METHODS ############
diff --git a/Modules/PrintMessage_Mod/__init__.py b/Modules/PrintMessage_Mod/__init__.py
index 89927cb..7d112a3 100644
--- a/Modules/PrintMessage_Mod/__init__.py
+++ b/Modules/PrintMessage_Mod/__init__.py
@@ -1,16 +1,16 @@
# 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/README.md b/README.md
index 6473a29..6d24f53 100644
--- a/README.md
+++ b/README.md
@@ -165,6 +165,21 @@ Meanwhile the program is cloning the repositories, the console will show message
+When finish, you look a final message (with the elapsed time of the execution) like this:
+
+
+
+ | Console Final Message |
+
+
+
+
+
+ |
+
+
+
+
@@ -224,7 +239,7 @@ for example:
{
"URL": "https://api.github.com/repos",
"USER": "CaidevOficial",
- "REPO": "Python_Udemy_DataManipulation",
+ "REPO": "Python_RepositoryCloner",
"BRANCH": "main"
},
"DataFrame": {
@@ -243,7 +258,7 @@ for example:
Then the code will make the link like:
```
-https://api.github.com/repos/CaidevOficial/Python_Udemy_DataManipulation/commits/main
+https://api.github.com/repos/CaidevOficial/Python_RepositoryCloner/commits/main
```
This way the program will take the 'Date' of the last commit of the branch 'main' and will use it to create the folder with the name of the repository. Obviously, the repository MUST BE PUBLIC, otherwise the program won't be able to access its API.