Git, GitHub and Vscode

First page of the Git cartoon
Second page of the Git cartoon

2 software and 1 website :

  • Create an account of github.com in my case, it will be pierre.jean@umontpellier.com
  • Download and install Git from https://git-scm.com/downloads
  • Download Zip version of VScode https://code.visualstudio.com/download according your internal processor (Windows usually x64, Mac usually universal) and unzip the file somewhere you usually install program (on the desktop in my case)

If you want to train more about Git you can use this page for beginner to advanced user : https://pierrejean.wp.imt.fr/2023/09/08/oh-my-git/

F&Q

  • With Git, there are several ways to do the similar thing…
  • The default branch could be main but it was common to have main.
  • Github is not the only website for Git: Gitlab, Sourcesup (Renater), Bitbucket, Amazon, etc. but Github is the most famous
  • VScode is different from Visual Studio from Microsoft

Very simple configuration on Github Website

On the GitHub account opens by click on the top right circle icon, then choose « Settings »

Then at the bottom, choose « Developper settings » at the bottom end :

Then Personal access tokens > Tokens (classic) or just follow https://github.com/settings/tokens , then « Generate a personal access token » :

Then you can provide a name of this token, give an expiration date (not perpetual), give right at least on repo rights and press the bottom button « Generate token » :

Then you have to copy the generated token, please be sure to copy the token because there is no way to give you back this one. If you lost it, you have just to create a new one.

You have to preserve somewhere those three informations from Github:

  • The email account used to create the github account
  • The account name used, you can find by clicking again of the top right small circle
  • The tokens key just generated

Github website provides the basic start we need on the first page you see after login creation or you can return with the Github icon or the « Dashboard » link :

At first, create a new private repository to practice call hello1 :

Then you have the quick look on commands that we will learn bellow:

Also, you need to keep the URL address like just the username of your account and the name of the repository for later as :

https://github.com/pierre-jean-dhm/hello1.git

If you need to change public/private settings or delete the repository, just click « Settings » and top bottom, you will find « Change repository visibility » and « Delete this repository« .


VScode and your folder

We will imagine, we will work into a folder on the desktop call Hello1 that could be empty of not. So create this Hello1 folder where we will work and you can see the full path into the Windows explorer address bar : C:\Users\pierre.jean\Desktop\Hello1\

Open the VScode folder and click on the code program to start it, choose « Open Folder… » and choose C:\Users\pierre.jean\Desktop\Hello1\

You can confirm, you trust the folder content (empty in my demonstration) :

Then, you can close the « welcome tab », open the terminal (Menu View > Terminal) and switch to « Source control » button on the left vertical bar.

So now into this terminal, just enter the following command but replace with the email address from the Github website :

git config user.email "pierre.jean@umontpellier.com"

You should have an error because the current folder is not setup for Git, so at first execute this command :

git init

VScode button « Initialize Repository » could also execute the same command just by pressing but there are so many terminal commands to learn instead…

You can see into the folder with « File explorer » (or Finder) there is a hidden file call .git :

Folder .git hidden visible via Menu « Display/Affichage » « Hidden elements/Elements masqués »

So you can call back the previous command (up arrow) to configure the email you preserve from the Github settings :

git config user.email "pierre.jean@umontpellier.com"

And the account name also from the

git config user.name "pierre-jean-dhm"

NOTE :If you want to change it, just call again the same command. And if you want to « un-git » the project, just delete the .git folder.

You can add a very new useful command line (git lg) with this command, so just copy and paste into the terminal and press ENTER:

git config alias.lg "log --oneline --all --decorate --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

Enter this command to use the main branch name instead of historical master branch name for all your project (so –global) :

git config --global init.defaultBranch main

But we need to rename the branc from master to main with :

git branch -m master main

Now, let’s start on a first project’s file.

NOTE: if a command ouput will not fit into the terminal area missing some place, you will see double dots:

So press SPACE key to see one more page until message END is shows then press Q key to quit.

NOTE2: if you close by mistake terminal, just open it again, Menu View >


Let’s start with versions control (Global Information Tracket)

1/ One new file, add and commit

Into the Hello1 folder, create a file equipe1.txt with menu File > New Text file

On the right, begin to enter text to remove the advice text « Select a language… », so enter :

Pierre

Save the file with equipe1.txt name :

Then we need to ask Git to follow this file equipe1.txt, inside the terminal enter :

git add equipe1.txt

We can also just click into the small + symbol to add this file « Stage Changes »:

Then create a first commit of this version of file with :

git commit -a -m "Initial version"

-a : for all file added previously

-m : to provide a message in this example « Initial version »

The « git commit » action is really to say « All those files are at the same point of development »

F&Q

  • Why to use git add : because some files could be into the folder and you do not want to include them into the version control
  • How to add several files and folders : with git add . or git add :/ to add everything into the current folder or everything into where you execute git init.
  • How to undo git add equipe1.txt : with git reset equipe1.txt
  • Why two command to add and commit : Several raisons, but I like to say: when I create a new file for a project, I add it at this moment into GIT with git add then later, I will include this file and more into the commit « package » with git commit.
  • Git and folders: GIT only manage files, if there is an empty folder, GIT will not manage it, so place a README.md file into and git add :/
  • Editor : You can use any editor as Notepad, UltraEdit, Matlab, etc. to create files but some editors will be updated by Git some other not, later it could be complex to close and reopen file each time to avoid troubles.
  • You can use arrow up to find a previous command
  • You can clear the terminal with cls or clear commands

We want to know what append into GIT so the previous command git lg will show us (or the short version git log –oneline –graph –all –decorate) :

We can display the status of our first commit with git log or git lg :

Each element is very important :

  • * : symbol for the active branch actually the main branch is call « main »
  • 727ce9e: short version of ID of the commit number, each commit will have a different version
  • HEAD : the position of the folder content files at present, the most important element
  • -> : very important symbol HEAD state is link to main state of the main branch
  • main : name of the first branch of commits (It could be master also)
  • Initial commit : the message of this version

The git lg command add more information, date of the commit and user name.

3/ Second version of our file

Edit the equipe1.txt file with this additional content and save it (CTRL+S):

Pierre
Gérard

Then commit this new version with the classical :

git commit -a -m "Team of 2 players"

Display the log via git lg (or git log –oneline –graph –all –decorate) :

We have 2 commits so we have two versions of our group of one file (equipe1.txt), the first version 727ce9e and the second is 939516a.

4/ Time machine

Suppose we can to go back to the first or previous version, you can either:

  • go to the version 727ce9e : with git checkout 727ce9e
  • go to the actual position (HEAD) minus one with : git checkout HEAD^
  • go to the actual position (HEAD) minus a number (here one) with : git checkout HEAD~1 or git checkout HEAD^1
git checkout HEAD^

We see the equipe1.txt file content change to display the previous content. So we move back in time, the content of our file change to display the previous version :

We return to the last commit with git checkout main.

F&Q

  • Version number of position: you should avoid to use version number all the time. There are HEAD~number, and there are branch name and tag and so much
  • How to go back into the future: git checkout main or git switch main
  • Detach HEAD, a HEAD is normally supposed to point on the last element of a branch, without a branch name HEAD is just a flag on the history of commits version.
  • Why you should not do git checkout baf9c8d : the situation is called a detached HEAD, in fact the version control of GIT will keep main branch pointing on the baf9c8d version. So if you created a new commit version you will have the following situation :
* e04c5e7 - (HEAD) version detach of branch (3 seconds ago) 
* 939516a - (main) Team of 2 players (63 minutes ago)
* 727ce9e - First commit (2 hours ago)

So the HEAD moves with the new version, but the branch name stayed on 939516a.

5/ VScode

You can use VScode to avoid most of the command, for example add a new file equipe2.txt into the folder Hello1. We don’t need to add a new file and a new commit, just a way to understand where are the buttons:

But VScode allow only to do git checkout with branch so …

6/ Branches

To avoid mix into the development, you have to think that your work will be share with someone. You should have 3 branches, your main/master branch, a develop/temporary/feature/test branch and the remote main/master branch.

First of all, where are in this situation :

* 939516a - (HEAD -> main) Team of 2 players (63 minutes ago) 
* 727ce9e - First commit (2 hours ago)

One file equipe1.txt with the following content :

Pierre
Gérard

We want to simulate a different way to develop our file. So we go back to the initial commit and we create a develop branch and try to work on :

git checkout HEAD~1
git branch develop

But we have to display the situation with git lg (of git log –oneline –graph –all –decorate) :

* 939516a - (main) Team of 2 players (2 hours ago) 
* 727ce9e - (HEAD, develop) First commit (4 hours ago)

There is a problem, HEAD is not linked to develop, HEAD is linked to 727ce9e and develop is linked alos on 727ce9e .

git checkout develop

Then git lg display :

* 939516a - (main) Team of 2 players (2 hours ago) 
* 727ce9e - (HEAD -> develop) First commit (4 hours ago)

Alternative, to avoid the detach HEAD, you could just, but don’t now :

git switch -c develop

To simulate this situation, we want to delete develop branch to recreate, so we have this situation :

* 939516a - (main) Team of 2 players (2 hours ago) 
* 727ce9e - (HEAD -> develop) First commit (4 hours ago)

Detach the HEAD with git checkout 727ce9e :

* 939516a - (main) Team of 2 players (2 hours ago) 
* 727ce9e - (HEAD, develop) First commit (4 hours ago)

Then delete the develop branch with :

git branch -d develop

Then we can create the new branch with :

git switch -c develop

Now we will update the file to create a new branch, edit equipe1.txt file as :

EQUIPE
##########
Pierre

Then commit this version and display situation ( -am is equivalent as -a -m) :

git commit -am "Nice version" 

Then display:

* 8c63cc4 - (HEAD -> develop) Nice version (22 seconds ago) 
| * 939516a - (main) Team of 2 players (31 minutes ago)
|/
* 727ce9e - Initial version (53 minutes ago)

Two branches : main to the main software development and develop to try some stuffs

VScode now allows to choose to checkout on a branch easily :

7/ Merge

Suppose we want to simulate some one who works on the main branch adding person to the list :

git checkout main

Then edit the file and save it with a third person as :

Pierre
Gérard
Killian

Then commit this new version with Vscode for example (note the dialog to ask to include -a or always) :

Or from the command line with :

git commit -am "Team of 3"

This is the situation :

* b123fa0 - (HEAD -> main) Team of 3 (3 seconds ago) 
* 939516a - Team of 2 players (39 minutes ago)
| * 8c63cc4 - (develop) Nice version (9 minutes ago)
|/
* 727ce9e - Initial version (62 minutes ago) <pierre-jean-dhm>

Then now return on the develop branch with :

git checkout develop

We want to merge the nice version of develop branch into the main branch with :

Or the command

git merge main

It could be possible the fusion is OK because there is no conflict really with this final result :

*  8c63cc4 - (HEAD -> develop) Merge branch 'main' into develop (71 minutes ago)
|\
| * b123fa0- (main) Team of 3 (74 minutes ago)
| * 939516a - Team of 2 players (4 hours ago)
* | 8c63cc4 - Nice version (78 minutes ago)
|/
* 727ce9e - First commit (5 hours ago)

Often, you will have a conflict with this interface :

Ok a bizarre and historical way to display content is sotred into equipe1.txt file, top a part from develop branch and bottom the part from main branch. You can have common part before and later the series of <<<<< and >>>>>>. But swith to « Merge editor with the nice button » :

Ok on the top left the part from main branch call incoming, on the top right, the part from the HEAD (current) develop branch and bellow, the final combinaison of the merge of content. Of course you can edit this final result content as you wish and then press « Complete Merge » to validate the merge.

BUT, is onlyj ust like we create a new content into the equipe1.txt file, we need to commit this new situation with:

git commit -am "Merge branch 'main' into develop"

What is our situation :

*   36bd9a0 - (HEAD -> develop) Merge branch 'main' into develop (81 seconds ago)
|\
| * b123fa0 - (main) Team of 3 (31 minutes ago)
| * 939516a - Team of 2 players (71 minutes ago)
* | 8c63cc4 - Nice version (40 minutes ago)
|/
* 727ce9e - Initial version (2 hours ago)

Next step a special case of merge

8/ Merge fast-forward

We are in a situation of the develop branch is one step forward the main branch. We can also now merge the develop branch into the main branch to simulate the preparation to share the main branch with other paople.

git checkout main
git merge develop

In this specific situation, Git succed to combine the content from develop branch equipe1.txt into main branch equipe1.txt.

To display difference, you can enter use this command (and yes we use ~1 as HEAD~1) :

git difftool -y -x sdiff develop main~1

Side by side :

EQUIPE                                           EQUIPE
########## ##########
Pierre / Pierre
Gérard <
Killian <

In this particular case, we do not have to commit because the merge succed without conflict.

So suppose we want to cancel this situation and just move the main branch label on the previsous commit identified by b123fa0 – Team of 3, we can have two solutions :

  • First option just move the branch on a spécific commit with :
 git branch -f main b123fa0
  • Second option move the HEAD with the main branch and return the HEAD on the develop branch:
git checkout main
git reset --hard b123fa0
git checkout develop

This initial situation at the end will be :

*   36bd9a0 - (HEAD -> develop) Merge branch 'main' into develop (40 minutes ago)
|\
| * b123fa0 - (main) Team of 3 (70 minutes ago)
| * 939516a - Team of 2 players (2 hours ago)
* | 8c63cc4 - Nice version (79 minutes ago)
|/
* 727ce9e - Initial version (2 hours ago)

This a way to cancel movement of the branch, but be aware that the main branch will be syncrhonise with a remote repository call remote origin/main.

Remote

Ok now everything we done is only local. We need to link to Github, so we need information keep at the begining as the git token (symbolise by ghp_XXXXXXXXX later) and the url :

https://github.com/pierre-jean-dhm/hello1.git

We need to create this termnal command with you information :

git remote add origin https://ghp_XXXXXXXXX@github.com/pierre-jean-dhm/hello1.git

In fac this will create a short name « origin » to your hello1.git repository. You can choose something other than origin as github but origin is really commun.

or we can use the Vscode menu insert at first the link https://ghp_XXXXXXXXX@github.com/pierre-jean-dhm/hello1.git then the name of the link origin as usual:

Please, do not accept Vscode to periodicaly fetch content, we do not need it at first.

We forget something, we want to push main branch and we are at present on develop branch. Think about it all the time please!

So option 1 just with this command line :

git push -u origin main

Or option 2, change to main branch then push :

or the command line :

git checkout main

Then git push to the remote repository with branch publish also:

The purpose at this moment is to have always main branch update and link to the remote branch.

You can go online to reresh the page and find everything:

  • Top left: the main branch
  • Top right: 3 commits from your computer
  • Center: our unique equipe1.txt file

You can open the file to see the last content and you can list all the commit to find history of commit or you can open the equipe1.txt file to see history also.

You can see the commit comments and unique number but only the main branch is uploaded.

In local you can see now there is a new remote origin/main branch with git lg command (or the short version git log –oneline –graph –all –decorate) :

* 36bd9a0 - (develop) Merge branch 'main' into develop (23 hours ago)
|\
| * b123fa0 - (HEAD -> main, origin/main) Team of 3 (23 hours ago)
| * 939516a - Team of 2 players (24 hours ago)
* | 8c63cc4 - Nice version (23 hours ago)
|/
* 727ce9e - Initial version (24 hours ago)

Now it is time to simulate a conflict with an external user.

Remote conflict

We will simulate a conflict between the origin/main branch and your local branch, on the main repository file you can click on the equipe1.txt file :

Then on the right, the pen button or the short menu then « Edit online » let you edit the file :

Change the content Equipe as bellow:

TEAM
##########
Pierre
Gérard
Killian

Then you have to « Commit » this new version with the top right button, this will open a dialog box to enter the messsage :

At this point, the online origin/main is updated but NOT your local version. There are two solutions from here BUT before please backup (see below) :

  • Download the remote origin/main branch to look what it could happen with : git fetch
  • Download the remote origin/main branch to stray away merge to your HEAD: git pull

How to backup this situation for training purpose

Just duplicate (copy/paste) the Hello1 folder somewhere to preserve the local situation. Git stores everything into the .git folder inside Hello1 folder, so backup this folder is equal to backup the local git folder. We can even imagine to delete the Github respository and recreate it (exception the last operation to edit online equipe1.txt will not be backup, because it still only exist online)

We can say « git fetch » and « git merge » is equivalent as « git pull ». Git fetch is the light version, you can download from Github but your ane not sure to use it. Git pull is you will download from Github but you use it at present.

This is the situation with git lg before git fetch:

*   36bd9a0 - (develop) Merge branch 'main' into develop
|\
| * b123fa0 - (HEAD -> main, origin/main) Team of 3
| * 939516a - Team of 2 players
* | 8c63cc4 - Nice version
|/
* 727ce9e - Initial version

after git fetch as a command on via menu

And again git lg to display :

* 327e940 - (origin/main) Add Team title 
| * 36bd9a0 - (develop) Merge branch 'main' into develop
| |\
| |/
|/|
* | b123fa0 - (HEAD -> main) Team of 3
* | 939516a - Team of 2 players
| * 8c63cc4 - Nice version
|/
* 727ce9e - Initial version

So we have a potentiel conflict display by Vscode betwen the main branch and the remote origin/main branch :

NOTE A optionnal compare with develop : We can also checkout the develop branch to try to merge with the origin/main branch to try to see what inspact it will be on the develop branch. Just try to merge, open the « Resolve into the Merge Editor » then to cancel enter command git merge –abort. Byt the way, how I know the command, just git status to display information. Just think to return on the main branch : git checkout main.

So option 1 : git merge will update directly the equipe1.txt content and the final situation will be main branch is identifical at origin/main branch :

* 327e940 - (HEAD -> main, origin/main) Add Team title 
| * 36bd9a0 - (develop) Merge branch 'main' into develop
| |\
| |/
|/|
* | b123fa0 - Team of 3
* | 939516a - Team of 2 players
| * 8c63cc4 - Nice version
|/
* 727ce9e - Initial version

And we also know a futur conflict will be with develop branch, but we will see that later.


Now go back to test option 2, close VScode, rename Hello1 folder into Hello1-Option1, copy the backup Hello1 into Hello1, restart Vscode, menu View Terminal and button on the top left bar « Source control » :

You can also open the equipe1.txt file (Menu File > Open File … ) Then git lg command :

*   36bd9a0 (develop) Merge branch 'main' into develop
|\
| * b123fa0 (HEAD -> main, origin/main) Team of 3
| * 939516a Team of 2 players
* | 8c63cc4 Nice version
|/
* 727ce9e Initial version

Ok now we wand to download the remote origin/main branch to stray away merge to your HEAD. We know online the last version is the best, we just want this version to be update with the main branch so go on.

At this point, because Git find a way to avoid conflict between the online version and the actual versio, juste equipe1.txt will work perfect and merge. We see on the screen, on the right, lines in yellow are copy to the left so everything is fine :

But suppose we merge with develop that for sure will create a conflict try with git merge develop then use the menu to create your combinaison of setting (Use CTRL+Z to cancel o Menu Edit > Undo)

I choose to create this content with « accept incomming » and edit the last line with ######:

EQUIPE
##########
Pierre
Gérard
Killian
########

Then press « Complete Merge » to finalise the conflict from main and develop, then create the new commit 36bd9a0 with this result from git lg output :

*   eefe254 - (HEAD -> main) Merge branch 'develop' (4 seconds ago) <pierre-jean-dhm>
|\
| * 36bd9a0 - (develop) Merge branch 'main' into develop (29 hours ago) <pierre-jean-dhm>
| |\
| * | 8c63cc4 - Nice version (30 hours ago) <pierre-jean-dhm>
* | | 327e940 - (origin/main) Add Team title (5 hours ago) <pierre-jean-dhm>
| |/
|/|
* | b123fa0 - Team of 3 (29 hours ago) <pierre-jean-dhm>
* | 939516a - Team of 2 players (30 hours ago) <pierre-jean-dhm>
|/
* 727ce9e - Initial version (30 hours ago) <pierre-jean-dhm>

We need to push to update origin/main as we always say to check main equal to origin/main

Ok now we have this situation with git lg :

*   eefe254 - (HEAD -> main, origin/main) Merge branch 'develop' 
|\
| * 36bd9a0 - (develop) Merge branch 'main' into develop
| |\
| * | 8c63cc4 - Nice version
* | | 327e940 - Add Team title
| |/
|/|
* | b123fa0 - Team of 3
* | 939516a - Team of 2 players
|/
* 727ce9e - Initial version

At this point, about develop branch, we could create a new develop branch for a new feature.

  • Delete develop branch and recreate it later
  • Merge develop branch with main branch to start later with this branch
  • Move the flag develop from 36bd9a0 to eefe254 and tag the commit with git tag develop-pretty-title
  • Rename develop branch as develop-pretty-title branch to keep this feature in mind

I recommand to keep the branch attach so rename a develop branch into an explicit name to keep in mind is the best. We will create later a develop-new-feature branch as needed. We don’t push this kind of branch on GitHub is just a way to work on side features instead have too much change on the main branch.

Simulate an other user

Create a new terminal independant of the first one, press ALT key and click to open a parallel terminal :

Enter the following command to go top folder, create a new folder, go insite this folder and then create a git account :

cd    ..
mkdir Hello1-other-user
cd Hello1-other-user
git init

We will create another account just my case swap family name and first name :

git config user.email "jean.pierre@umontpellier.fr"
git config user.name "JEAN Pierre"

Now we will simulate a new challenger on this project who want to clone from the remote GitHub folder the whole project with the same token:

git remote add origin https://ghp_XXXXXX@github.com/pierre-jean-dhm/hello1.git

Then download the whole main branch from origin :

git pull origin main

We are suppose now to image a large contribution from this new user, open the file equipe1.txt in parallel with this combinaison :

Open the menu File > Open files … then move to one up folder, then choose the other sub folder called Hello1-other-user then open equipe1.txt file :

Then you can displays both file, right click on the tab to choose « Split Right » menu

And after close this tab because Split Right duplicate

Now we can display at the left equipe1.txt file from Hello1 and its console and at the right equipe1.txt file from Hello1-other-user and its console :

This exercice suppose to work on this specific situation:

  • The right user will create a new developer-complex-feature branch and create one commit on the files, for example add email for the first person
  • But the left user will works on the main branch and add two more commits with more peoples on the list
  • The right user knows there are update but he needs more time to work on his file but he can wait to receive update

With the right user

git branch developer-complex-feature
git checkout developer-complex-feature
# edit the file adding an email
git commit -am "Update email first person"

With the left user

# edit the file adding one more people
git commit -am "Teams of 4 peoples"
# edit the file adding one more people
git commit -am "Teams of 5 peoples"
git push origin main

With the right user need to receive update

git pull origin main
git checkout main
git merge origin/main

Now we have this situation :

* 629b770 - (HEAD -> main, origin/main) Teams of 5 peoples (4 minutes ago)
| * 19eb774 - (developer-complex-feature) Update email first person (7 minutes ago)
|/
* eefe254 - Merge branch 'develop' (3 days ago)
|\
| * 36bd9a0 - Merge branch 'main' into develop (4 days ago)
| |\
| * | 8c63cc4 - Nice version (4 days ago)

So developer-complex-feature is link to eefe254 commit and it is « too early » we need more time, so we can move the branch (call rebase) from eefe254 to a more recent commit into the timeline, so :

git checkout developer-complex-feature
git rebase main

So the new situation will be :

* d5338af - (HEAD -> developer-complex-feature) Update email first person (5 seconds ago) 
* 629b770 - (origin/main, main) Teams of 5 peoples (5 minutes ago)
* eefe254 - Merge branch 'develop' (3 days ago)
|\
| * 36bd9a0 - Merge branch 'main' into develop (4 days ago)
| |\
| * | 8c63cc4 - Nice version (4 days ago)

And right user can work on more updated content from equipe1.txt file and the content is :

EQUIPE
##########
Pierre p.j@mine_ales.com
Gérard
Killian
Simon
Stéphane
########

A very important information : never rebase a online branches like main branch.

You can simulate more commits for the left user and rebase for the right user until right user finish and push modifications on Github main branch.

At the end, change everything on the developer-new-feature branch, save file and commit the change into a new commit :

git commit -am "Update emails"

We can merge from developer-new-feature branch, we need to move on the main branch and merge and push :

git checkout main
git merge developer-new-feature
git push origin main

You can go online to find the Github commit page and display commit from the right user and commit from the left user :

Ok of course, you can now git pull origin main for the left user and go on simulate conflict and development. We can see also with the classic git lg command :

* 7551fa3 - (HEAD -> main, origin/main) Update emails <JEAN Pierre>
* d5338af - Update email first person <JEAN Pierre>
* 629b770 - Teams of 5 peoples <pierre-jean-dhm>
* eefe254 - Merge branch 'develop' <pierre-jean-dhm>
|\
| * 36bd9a0 - (develop) Merge branch 'main' into develop <pierre-jean-dhm>
| |/
|/|
* | b123fa0 - Team of 3 <pierre-jean-dhm>
* | 939516a - Team of 2 players <pierre-jean-dhm>
|/
* 727ce9e - Initial version (4 days ago) <pierre-jean-dhm>

Additionnals operations

Hide files from Git

Put a word document into the folder, you will see it all the time not « added » (not tracked) by Git :

So you can create a .gitignore file with the following content and save it into the same folder where your execute git init (Hello1 in ours case) :

*.docx
*.pdf
*.xlsx
*.pptx

All files with .docx, .pdf, .xlsx, *.pptx will be ignored by Git. Off couse, you will se that you can tracked (git add) the .gitignore file or you can add .gitignore at the end of your .gitignore file.

Many websites provide sample for .gitignore file: https://github.com/github/gitignore

Move files and git status

Suppose you create a new file equipe2.txt into the folder with the folowing content:

EQUIPE
###########

You can add to git the « untracked/unstaged » file with the git add but you forget. Many time if you need to understand which command will be more usuful just enter git status :

On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
(use "git add <file>..." to include in what will be committed)
equipe2.txt

nothing added to commit but untracked files present (use "git add" to track)

Use git add or the plus button to add the file and enter git status :

On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: equipe2.txt

So to rever the git add command, you will see the command :

git restore --staged equipe2.txt

Now move to develop branch, git add equipe2.txt file and commit

git checkout develop
git add equipe2.txt
git commit -m "Add equipe2 file"

Now suppose you want to cancle last commit has it never exists :

git reset --soft HEAD~1

The git status will display the moment after the git add :

On branch develop
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: equipe2.txt

Add authentication to Github easely

You can download the Github client with https://cli.github.com/ and install it on your computer. Then start this command from Windows terminal:

"c:\Program Files\GitHub CLI\gh.exe" auth login

You will be ask for severals questions as (my answers are in bleu):

? What account do you want to log into?  GitHub.com  
? What is your preferred protocol for Git operations on this host? HTTPS
Authenticate Git with your GitHub credentials? No
How would you like to authenticate GitHub CLI? Paste an authentication token

Then you will can paste you generated token but before you must add to it right read:org :

Then you terminal will be link to Github website. You can confirm with :

"c:\Program Files\GitHub CLI\gh.exe" auth status

github.com
✓ Logged in to github.com account pierrejean (keyring)
- Active account: true
- Git operations protocol: https
- Token: ghp_************************************
- Token scopes: 'read:org', 'repo'
Publié dans Développement, EuroMov DHM | Laisser un commentaire

Git, Gihub and Github desktop

2 software and 1 website :

  • Create an account of github.com in my case, it will be pierre.jean@umontpellier.com
  • Download and install Git from https://git-scm.com/downloads
  • Download and NOT install Github Desktop for now https://desktop.github.com/

If you want to train of Git you can use this page for beginner to advanced user : https://pierrejean.wp.imt.fr/2023/09/08/oh-my-git/

F&Q

  • With Git, there are several ways to do the similar thing…
  • The default branch could be master or now it is more common to have main as name of the central branch.
  • Github is not the only web site for Git: Gitlab, Sourcesup (Renater), Bitbucket, Amazon, etc but Github is the most famous

Very simple configuration on Github Website

On the Github account opens by click on the top right circle icon, then choose « Settings »

Then at the bottom, choose « Developper settings » at the bottom end :

Then Personal access tokens > Tokens (classic) or just follow https://github.com/settings/tokens , then « Generate a personal access token » :

Then you can provide a name of this token, give an expiration date (not perpetual), give right at least on repo rights and press the bottom button « Generate token » :

Then you have to copy the generated token, please be sure to copy the token because there is no way to give you back this one. If you lost it, you have just to create a new one.

You have to preserve somewhere those three informations from Github:

  • The email account used to create the github account
  • The account name used, you can find by clicking again of the top right small circle
  • The tokens key just generated

Github website provides the basic start we need on the first page you see after login creation or you can return with the Github icon or the « Dashboard » link :

At first, create a new private repository to practice call hello1 :

Then you have the quick look on commands that we will learn bellow:

Also, you need to keep the URL address like just the username of your account and the name of the repository for later as :

https://github.com/pierre-jean-dhm/hello1.git

Git on your computer

Git is an open source software to manage a local version of a hard drive folder with files. Create on your desktop a folder call Projet1 with « File explorer » (Windows) or « Finder » (MacOS). You have to find the path of this folder with « File explorer » is into the top address bar.

C:\Users\pierre.jean\Desktop\Projet1\ in my case (keep into your mind) for the next step :

C:\Users\pierre.jean\Desktop\Projet1\

MacOS users will have to drag and drop the folder to a terminal application to show the path

So open terminal application and enter the following command :

cd "C:\Users\pierre.jean\Desktop\Projet1\"

If the combination of folders named as a path include no spaces you can enter simply :

cd C:\Users\pierre.jean\Desktop\Projet1\

Mac OS user can drag and drop the folder into the terminal to have the path. Windows users can replace into the « file explorer » address bar the content and enter « cmd » and press ENTER to open the terminal into the correct place.

NOTE: cd is fo Change Directory

Configuration of local git settings

So now into this terminal, just enter the following command but replace with the email address from the Github website :

git config user.email "pierre.jean@umontpellier.com"

You should have an error because the current folder is not setup for git so at first execute this command :

git init

You can see into the folder with « File explorer » (or Finder) there is a hidden file call .git :

Folder .git hidden visible via Menu « Display/Affichage » « Hidden elements/Elements masqués »

So you can call back the previous command (up arrow) to configure the email you preserve from the Github settings :

git config user.email "pierre.jean@umontpellier.com"

And the account name also from the

git config user.name "pierre-jean-dhm"

If you want to change it, just call again the same command. And if you want to « un-git » the project, just delete the .git folder.

You can add a very useful command line ( git lg) with this command

git config alias.lg "log --oneline --all --decorate --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%ae>%Creset' --abbrev-commit"

Let’s start with versions control (Global Information Tracket)

1/ One new file, add and commit

Into the Projet1 folder, create a file equipe1.txt with notepad or any text editor to manage information about a team with a line of information as below:

Pierre

Then ask Git to follow this file equipe1.txt, inside :

git add equipe1.txt

Then create a first commit of this version of file with :

git commit -a -m "Initial version"

-a : for all file added previously

-m : to provide a message in this example « Initial version »

The « git commit » action is really to say « All those files are at the same point of developpement »

F&Q

  • Why to use git add : because some files could be into the folder and you do not want to include them into the version control
  • How to add several files and folders : with git add . or git add :/ to add everything into the current folder or everything into where you execute git init.
  • How to undo git add equipe1.txt : with git reset equipe1.txt
  • Why two command to add and commit : Several raisons, but I like to say: when I create a new file for a project, I add it at this moment into GIT with git add then later, I will include this file and more into the commit « package » with git commit.
  • Git and folders: GIT only manage files, if there is an empty folder, GIT will not manage it, so place a README.md file into and git add :/
  • Editor update: some editor will be updated by Git some other not, later it could be complex to close and reopen file each time to avoid troubles.

2/ Check state

We want to know what append into GIT so the previous command git lg will show us (or the short version git log –oneline –graph –all –decorate) :

We can display the status of our first commit with gitlog or git lg :

Initial commit log display short visible version

Each element is very important :

  • * : symbol for the active branch actually the main branch is call « master »
  • 58d31e1 : short version of ID of the commit number, each commit will have a different version
  • HEAD : the position of the folder content files at present, the most important element
  • -> : very important symbol HEAD state is link to master state of the main branch
  • master : name of the first branch of commits (It could be main also)
  • Initial commit : the message of this version

The git lg command add more information, date of the commit and email of the user.

3/ Second version of our file

Edit the equipe1.txt file with this additional content :

Pierre
Gérard

Then commit this new version with the classical :

git commit -a -m "Team of 2 players"

Display the log via gitlog

Git log second commit

We have 2 commits so we have two versions of our group of one file (equipe1.txt), the first version 58d31e1 and the second is baf9c8d.

4/ Time machine

Suppose we can to go back to the first or previous version, you can either:

  • go to the version baf9c8d: with git checkout baf9c8d
  • go to the actual position (HEAD) minus one with : git checkout HEAD^
  • go to the actual position (HEAD) minus a number (here one) with : git checkout HEAD~1 or git checkout HEAD^1

Now reopen the file equipe1.txt to found the previous content. So we move back in time, the content of our file change to rescue the previous version :

Git checkout previous version

We can look the content of the file and find only one line « Pierre » as the content prepare when we create the « Initial commit ».

F&Q

  • Version number of position: you should avoid to use version number all the time. There are HEAD~number, and there are branch name and tag and so much
  • How to go back into the future: git checkout master or git switch master
  • Detach HEAD, a HEAD is normally supposed to point on the last element of a branch, without a branch name HEAD is just a flag on the history of commits version.
  • Why you should not do git checkout baf9c8d : the situation is called a detached HEAD, in fact the version control of GIT will keep master/main branch pointing on the baf9c8d version. So if you created a new commit version you will have the following situation :
* e04c5e7 - (HEAD) version detach of branch (3 seconds ago) 
* baf9c8d - (master) Team of 2 players (63 minutes ago)
* 58d31e1 - First commit (2 hours ago)

So the HEAD moves with the new version but the branch name stayed on baf9c8d. Alway checkout to the last branch name.

5/ Branches

To avoid mix into the development, you have to think that your work will be share with someone. You should have 3 branches, your main/master branch, a develop/temporary/feature/test branch and the remote main/master branch.

First of all, where are in this situation :

* baf9c8d - (HEAD -> master) Team of 2 players (63 minutes ago) 
* 58d31e1 - First commit (2 hours ago)

One file equipe1.txt with the following content :

Pierre
Gérard

We want to simulate a different way to develop our file. So we go back to the initial commit and we create a develop branch and try to work on :

git checkout HEAD~1
git branch develop

But we have to display the situation with git lg (of git log –oneline –graph –all –decorate) :

* baf9c8d - (master) Team of 2 players (2 hours ago) 
* 58d31e1 - (HEAD, develop) First commit (4 hours ago)

There is a problem, HEAD is not linked to develop, HEAD is linked to 58d31e1 and develop is linked alos on 58d31e1.

git checkout develop

Then git lg display :

* baf9c8d - (master) Team of 2 players (2 hours ago) 
* 58d31e1 - (HEAD -> develop) First commit (4 hours ago)

Alternative, to avoid the detach HEAD, you could just, but don’t now :

git switch -c develop

To simulate this situation, we want to delete develop branch to recreate, so we have this situation :

* baf9c8d - (master) Team of 2 players (2 hours ago) 
* 58d31e1 - (HEAD -> develop) First commit (4 hours ago)

Detach the HEAD with git checkout 58d31e1 :

* baf9c8d - (master) Team of 2 players (2 hours ago) 
* 58d31e1 - (HEAD, develop) First commit (4 hours ago)

Then delete the develop branch with :

git branch -d develop

Then we can create the new branch with :

git switch -c develop

Now we will update the file to create a new branch, edit equipe1.txt file as :

EQUIPE
##########
Pierre

Then commit this version and display situation ( -am is equivalent as -a -m) :

git commit -am "Nice version" 

Then display:

* d1e4a2c - (HEAD -> develop) Nice version (4 seconds ago) 
| * baf9c8d - (master) Team of 2 players (2 hours ago)
|/
* 58d31e1 - First commit (4 hours ago)

6/ Merge

Suppose we want to simulate some one who works on the master branch adding person to the list or master branch:

git checkout master

Then edit the file with a third person as :

Pierre
Gérard
Killian

Then commit this new version with :

git commit -am "Team of 3"

This is the situation :

* 6eac561 - (HEAD -> master) Team of 3 (2 seconds ago) 
* baf9c8d - Team of 2 players (3 hours ago)
| * d1e4a2c - (develop) Nice version (5 minutes ago)
|/
* 58d31e1 - First commit (4 hours ago)

Then now return on the develop branch with :

git checkout develop

* 6eac561 - (master) Team of 3 (87 seconds ago)
* baf9c8d - Team of 2 players (3 hours ago)
| * d1e4a2c - (HEAD -> develop) Nice version (6 minutes ago)
|/
* 58d31e1 - First commit (4 hours ago)

We want to merge the nice version of develop branch into the master branch with :

git merge master

Then we will have the fusion because there is no conflict with this final result :

*   d153307 - (HEAD -> develop) Merge branch 'main' into develop (71 minutes ago)
|\
| * 6eac561 - (master) Team of 3 (74 minutes ago)
| * baf9c8d - Team of 2 players (4 hours ago)
* | d1e4a2c - Nice version (78 minutes ago)
|/
* 58d31e1 - First commit (5 hours ago)

You can display the merge file equipe1.txt Git succed to combine file in this case:

EQUIPE
##########
Pierre
Gérard
Killian

But we are lucky, equipe1.txt file from master/main branch have commun element from equipe1.txt from develop branch. you can display this information with this command (and yes we use ~1 as HEAD~1:

git diff develop~1 master

This will display difference beetwen 6eac561 and d153307 with :

diff --git a/equipe1.txt b/equipe1.txt
index 6eac561..d153307 100644
--- a/equipe1.txt
+++ b/equipe1.txt
@@ -1,3 +1,3 @@
-EQUIPE
-##########

Pierre
+Gérard
+Killian

Red element if for the develop branch, Pierre element is common and green element if for main/master branch.

To cancel and go back to previous situation, you can move the HEAD and develop branch name by moving it (and we will lose d153307)

git reset --hard  d1e4a2c

7/ Merge conflict

Now we want a real conflict, so edit the equipe1.txt file from develop branch and remove Pierre and insert Simon :

EQUIPE
##########
Simon

Now commit this new version with :

git commit -am "Pretty and Simon" 

So now we can look a potential merge conflict before by compare :

git diff --word-diff=color develop master

Result show a conflict on the third line :

-EQUIPE
-##########
Simon
Pierre
Gérard
Killian

So we know it will be a problem with the futur merge.

We can display also side by side with :

 git difftool -y -x sdiff develop master

EQUIPE | Pierre
########## | Gérard
Simon | Killian

So we will create the merge conflict with :

git merge master

This will display the conflict message :

Auto-merging equipe1.txt
CONFLICT (content): Merge conflict in equipe1.txt
Automatic merge failed; fix conflicts and then commit the result.

We can display the file and it is a mess :

<<<<<<< HEAD
EQUIPE
##########
Simon
=======
Pierre
Gérard
Killian
>>>>>>> master

Ok just to read it I had color as git diff

<<<<<<< HEAD
-EQUIPE
##########
Simon

=======
Pierre
Gérard
Killian

>>>>>>> master

The simpliest solution is just remove everything from git merge (<<<<< , >>>>> and =====) to create ours merged version and even add information and save it :

EQUIPE
##########
Simon

Pierre
Gérard
Killian

Adam

Then to finish create the commit :

git commit -am "Combine pretty and team of 3 plus Adam"

Finaly, we have got :

*   9ddbc45 - (HEAD -> develop) Combine pretty and team of 3 plus Adam (22 minutes ago)
|\
| * 6eac561 - (master) Team of 3 (15 hours ago)
| * baf9c8d - Team of 2 players (18 hours ago)
* | 8f1fead - Pretty and Simon (47 minutes ago)
* | d1e4a2c - Nice version (15 hours ago)
|/
* 58d31e1 - First commit (19 hours ago)

But master/main branch is not update, we should move in parallel. Finish, we merge develop to main/master. This time no conflict, Git knows what comme from develop and what comme from main:

git checkout master 
git merge develop

Then we can see HEAD is on master and develop branch is also on the last commit :


* 9ddbc45 - (HEAD -> master, develop) Combine pretty and team of 3 plus Adam (22 minutes ago)
|\
| * 6eac561 - (master) Team of 3 (15 hours ago)
| * baf9c8d - Team of 2 players (18 hours ago)
* | 8f1fead - Pretty and Simon (47 minutes ago)
* | d1e4a2c - Nice version (15 hours ago)
|/
* 58d31e1 - First commit (19 hours ago)

Remote

Ok now everything we done is only local. We need to link to Github, so we need information keep at the begining as the git token (symbolise by ghp_XXXXXXXXX later) and the url :

https://github.com/pierre-jean-dhm/hello1.git

We need to create this command with you information :

git remote add origin https://ghp_XXXXXXXXX@github.com/pierre-jean-dhm/hello1.git

In fac this will create a short name « origin » to your hello1.git repository. You can choose something other than origin as github but origin is really commun.

At first, I want to rename master branch as main with :

git branch -M master main

Then I will push with :

git push -u origin main

The -u parameter (or –set-upstream) is to devine the default branch to later do not have to write all the time you want the main branch.

You can go online to reresh the page and find everything:

  • Top left: the main branch
  • Top right: 6 commits from your computer
  • Center: our unique equipe1.txt file

You can open the file to see the last content and you can list all the commit to find history of commit or you can open the equipe1.txt file to see history also.

You can see the commit comments and unique number but only the main branch is uploaded.

In local you can see now there is a new remote origin/main branch with git lg command (or the short version git log –oneline –graph –all –decorate) :

*   9ddbc45 - (HEAD -> main, origin/main, develop) Combine pretty and team of 3 plus Adam (2 hours ago)
|\
| * 6eac561 - Team of 3 (17 hours ago)
| * 6c6fd31 - Team of 2 players (20 hours ago)
* | 8f1fead - Pretty and Simon (3 hours ago)
* | d1e4a2c - Nice version (17 hours ago)
|/
* 633f1e4 - First commit (21 hours ago)

Remote conflict

We will simulate a conflict between the origin/main branch and your local branch, on the main repository file you can click on the equipe1.txt file :

Then on the right, the pen button or the short menu then « Edit online » let you edit the file :

Change the content Equipe becomes TEAM :

TEAM
##########
Simon
Pierre
Gérard
Killian
Adam

Then you have to « Commit » this new version with the top right button, this will open a dialog box to enter the messsage :

At this point, the online origin/main is updated but not your local version. There are two solutions from here :

  • Download the remote origin/main branch to look what it could happen with : git fetch
  • Download the remote origin/main branch to stray away merge to your HEAD: git pull

We can say « git fetch » and « git merge » is equivalent as « git pull ». Git fetch is the light version, you can download from Github but your ane not sure to use it. Git pull is you will download from Github but you use it at present.

The situation at present with git lg before git fetch:

*   9ddbc45 - (HEAD -> main, origin/main, develop) Combine pretty and team of 3 plus Adam (2 hours ago)

after git fetch and again git lg to display :

* 70735d2 - (origin/main) Change Equipe to Team (6 minutes ago) 
* 9ddbc45 - (HEAD -> main, develop) Combine pretty and team of 3 plus Adam (3 hours ago)

Ok know we can see the the difference :

git diff --word-diff=color origin/main main

This will display :

TEAMEQUIPE
##########
Simon
Pierre
Gérard
Killian
Adam

Ok three strategies :

  • git merge origin/main to have the remote origin/main version with TEAM word
  • git merge –strategy=ours origin/main to have the local main version with EQUIPE word
  • git merge –no-ff origin/main this is a very useful one that will create a new commit from the merge of origin/main and main branches without fast-forward strategy to merge into the actual commit.

Let look the result of this last git merge –no-ff origin/main with git lg command :

*   24e02d5 - (HEAD -> main) Merge remote-tracking branch 'origin/main' (10 seconds ago) 
|\
| * 70735d2 - (origin/main) Change Equipe to Team (71 minutes ago)
|/
* 9ddbc45 - (develop) Combine pretty and team of 3 plus Adam (4 hours ago)

So the equipe1.txt include a merge of the two branch so this is the content :

TEAM
##########
Simon
Pierre
Gérard
Killian
Adam

But we want to decide better how to manage the content into the merge. So now switch to a new tool GitHub Desktop

GitHub Desktop

Install GitHud Desktop now, but we will skip the Github authentication to test again Git.

Step one « Skip the Github authentication » we will authenticate at first with token and later we could « Sign in to Github.com » :

Enter nothing or your username and email as we store at the top of this exercice. Why noting : because informations are store into the .git folder of this repository (remeber git config user.email) :

Then now the important, we ask GitHup Desktop to manage the Git local folder c:\Users\pierre.jean\Dekstop\Projet1\

Let start with the GitHub Desktop :

  • Top left button: to change the repository, at present we have only one Projet1
  • Middle top button, you can see and change branch as git checkout, you can also merge branch into this windows
  • Top right button Git pull origin or the small one git fetch (git pull = git fetch + git merge)
  • History menu : as git lg we will see later
  • Large left white area: List of potential files to git add, at present no file, create a new text file into the Projet1 folder and you will see there, then delete it
  • Git commit message area as we did with git commit -am « message area »
  • Git commit description : not used
  • Commit to main : the commit button to create a new commit

At this point, we have the same operation on the classic process to modify files, add new files, commit and push. One drawback, nothing display the remote origin/main branch at this moment with GitHub Desktop. We will see how to manage this point later.

You can use now the « History » button to display list on the main current branch the evolution of the content of the equipe1.txt file :

On the « First commit », you will find only Pierre, then adding Gérard.

The « Nice version » is suppose to be into the develop branch, but everything is merge into the last commit and so Github Desktop display everything.

GitHub Desktop philosophy

As you can see on the first screen, GitHub Desktop show us this message in blue : « Pull 1 commit from the origin remote » :

In fact, GitHub Desktop wants the main branch is synchronize all the time to the remote origin/main. At present git lg shows us :

* 70735d2 - (origin/main, origin/HEAD) Change Equipe to Team 
* 9ddbc45 - (HEAD -> main, develop) Combine pretty and team of 3 plus Adam
|\
| * 6eac561 - Team of 3
| * 6c6fd31 - Team of 2 players
* | 8f1fead - Pretty and Simon
* | d1e4a2c - Nice version

GitHub Desktop wants you merge local main branch and origin/main. And it also adds origin/HEAD that I don’t know why (event after I delete it, it comes back).

Anyway, we are suppose to have a local main branch always equals to origin/main branch.

So we should develop on the develop branch and then merge to the local main branch and then push to the remote origin/main branch.

So press button : « Pull origin » to receive the last commit « Change Equipe to Team » and the equipe1.txt file contents will be :

TEAM
##########
Simon
Pierre
Gérard
Killian
Adam

So main branch and remote origin/main branche are equals now. I still have develop branch with equipe1.txt contains :

EQUIPE
##########
Simon
Pierre
Gérard
Killian
Adam

Two options:

  • I want to move develop branch on the last commit from the origin/main branch (= main branch)
  • I want to preserve the content from develop branch

1/ Option 1: Develop branch = local main branch = remote origin/main branch

This strategy is remote content is the correct solution with TEAM word.

  • Change to the develop branch
  • Choose to create a merge commit from the main branch.
  • Press « Create a merge commit » to confirm the merge
  • A new commit is « added » to the develop branch and this commit is just the same of main branch, see git lg :
* 70735d2 - (HEAD -> develop, origin/main, origin/HEAD, main) Change Equipe to Team 
* 9ddbc45 - Combine pretty and team of 3 plus Adam
|\
| * 6eac561 - Team of 3

You can go on work on the develop branch until you merge with the main branch.

2/ Option 2: local main branch has to update then remote origin/main branch will be update

This strategy is the local content is the correct solution with EQUIPE word. We cannot merge because develop branch is an ancestror of main branch.

* 70735d2 - (HEAD -> main, origin/main) Change Equipe to Team
* 9ddbc45 - (develop) Combine pretty and team of 3 plus Adam
|\
| * 6eac561 - Team of 3

We could imagine to create a new commit from develop branch change something then merge to simulate and update on the develop.

We will just choose the previous commit and right click to create a new commit with the previous content :

The git lg command will show:

* 161d109 - (HEAD -> main) Revert "Change Equipe to Team"
* 70735d2 - (origin/main, origin/HEAD) Change Equipe to Team
* 9ddbc45 - (develop) Combine pretty and team of 3 plus Adam
|\
| * 6eac561 - Team of 3 (26 hours ago) <pierre.jean@umontpellier.fr>

Now we can push the new modification and delete the develop branch and recreate it on the HEAD.

Publié dans Développement | Laisser un commentaire

Protégé : Git test

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Publié dans Blog, Développement | Saisissez votre mot de passe pour accéder aux commentaires.

Web Development TP 1

Using green resources of the computer

At first, to preserve resources, close any other applications except web development browser, eclipse and tomcat server.

You can decrease the CPU frequency by change the level of power save, reduce temporary the light of the screen at a comfortable level for your eyes. Also, please reduce the number of tabs and windows from your browser.

1/ Description Application Todo

Our main application will be to manage a list of thing to do, as for example the shopping list :

The Model part of the MVC will be simplest to let us work on the MVC with Web Development tools. Only one business rule is provided « no double entry », for example if someone try to add again « chocolat » at the list, there are no error but only one « chocolat » will stay into the list (case-insensitive). This is the unique business rule or our simple model layout.

Please find below a « very very » simple Class Diagram at starting point, you will have to add content and improve it :

To manage easily one unique instance of the application, a Singleton Design Pattern is provided as this draft :

public class Application {
   private static Application instance = null;
   
   public static Application getInstance() {
      if (instance == null) {
           instance = new Application ();
      }
      return instance;
     }

  private Application() {
    // Initialization of the List 
  }

}

So please think about to instanciate a new application without access to the private constructor ?

How to initialize the list of todo items call « lesTodos » with the draft code

Could you please use the Interface List from java.util.List for futur integration and evolution.

NOTE: une interface do not provide all the code only signature of methods as show into the code :

Do not hesitate to open Java code by CTRL+left click on a class of a function, to study the difference between ArrayList and List.

Keep in mind that a future evolution of the project could use a LinkedList or a Stream result as we will see later.

Please study mainly methods contains, get and indexOf into ArrayList class.

2/ Project creation with only business/model part

Create a new project « Dynamic Web Project » ( File > New > Dynamic Web project), then deploy your project into Tomcat 9 installed previously with righ clic > « Add and Remove … » to add this project to Tomcat.

Create a new package into the « Java Ressources » part of the project :

We need a top package call main (name of package must be in lowercase at the opposite for class with the first capital letter) with insides packages model, control and test.

Code classes Application and Todo with additional methods depending your need withe righ clic on the package model and menu New > Class, you can tick to implement « public static void main (String[] args) » to test the class as a simple Java program.

You can generate Getter and Setter with right click mouse on the code and Menu Source > Generate Getters and Setters…

Use the generation of method hashCode() and equals() using only the field « texte » because comparing 2 instances of todo only this field is mandatory (business rule).

You can also generate the method toString() on the class Application but I recommend to you to learn to debug this class.

Create additional constructors with all fields, only texte field and with no fields with the Menu Source > Generate Constructor using Fields.

Please consider test comparing class with the main method :

public static void main (String[] args){
  Todo todo1 = new Todo( "lait", false );
  Todo todo2 = new Todo( "beurre", true);

   if ( todo1.equals( todo2 ) ) {
    System.out.println(" lait equals beurre ");
   }

   todo2.setText( "lait" );
   if ( todo1.equals( todo2 ) ) { 
     System.out.println(" lait equals lait ");
   }
}

To test a class, just right-click on the code and choose Menu > Debug As > Java Application, output is displayed in « Console » tab, or you can add breakpoint to understand features of equals() method.

NOTE: hashCode() return a value to organize instance of the same class by order. In our application the information will not be used but in case of extreme large number of instance, it could be useful to group instance for speed up processing.

Again, use the « public static void main (String[] args) » method to debug call of Application singleton by using this code:

public static void main(String[] args){
  Application.getInstance().addTodo("lait");
  Application.getInstance().addTodo("beurre");
  Application.getInstance().addTodo("lait");

}

Then you can also try to add additional method to Application for example several methods call findTodo() should be very useful.

3/ Unit Test with Junit4

In fact, the calling on « public static void main (String[] args) » method to test our program is not the best way to test the model part. We will use a Test Framework call JUnit to test Application class.

By the past, I let students start by testing Todo class first, but they find testing getters and setters less interesting, so let’s start with ApplicationTest. You will find an example of basic TodoTest application below, you could study particlary the testEqualsObject() method design to check the model business rule :

class TodoTest {
	@Test
	void testTodo() {
	    Todo todo = new Todo("chocolat" , false);
	    assertNotNull( todo );
	}
	@Test
	void testTodoNoParameters() {
	    Todo todo = new Todo();
 	    assertNotNull( todo.getTexte() );
	}
	@Test
	void testGetTexte() {
	     Todo todo = new Todo("chocolat" , false);
	     assertEquals ( todo.getTexte() , "chocolat");
	}
	@Test
	void testSetTexte() {
	    Todo todo = new Todo("chocolat", false);
	     todo.setTexte("ananas");
	     assertEquals ( todo.getTexte() , "ananas");
	}
	@Test
	void testSetActif() {
	     Todo todo = new Todo("chocolat" , false);
	     todo.setActif(true);
	     assertTrue( todo.isActif());
	}
	@Test
	void testIsActif() {
	     Todo todo = new Todo("chocolat" , false);
	     assertFalse( todo.isActif());
	}
	@Test
	void testEqualsObject() {
	     Todo todo1 = new Todo("chocolat" , false);
	     Todo todo2 = new Todo("chocolat" , true);
	     assertTrue( todo1.equals(todo2));
	}
}

On the class Application, right click to open Menu « New > Other > Junit Test Case » then fill the windows by providing the package model to store this new ApplicationTest class.

Please check methods @BeforeAll @BeforeEach, @AfterAll, @AfterEach and on the next windows, check method you want to test, obviously all method your create into Application.

One dialog will ask you to « Add Junit 5 library to the build path », please confirm by pressing OK to download and install Junit library to create test.

NOTE: if you forget one step, just delete the ApplicationTest class and start over.

NOTE: if for any reason, the ApplicationTest class is stored into the wrong package, just move into the package test.

To execute a Unit Test Case, just right-click on the code and chose Menu Debug As > Junit Test and you can check un green bar to display if all tests pass:

If a test fail, you will find a red bar, the console message, the number of failure test and of course which test fail :

You can debug with a breakpoint any test to understand why this test failed as any other Java code. Keep in mind, the writer of the code is not usually the person who writes the test code.

NOTE: a different way of wriing code is to write test code then write the missing code so in our case writing ApplicationTest then writing Application class.

Now we want to test at least :

  • Singleton is never null
  • 2 references of Application are equals
  • list of todos is empty at start
  • add a todo to the list and that the list increase by one
  • add a todo and find it
  • add a todo and it is the last todo of the list
  • delete a todo and do not find it into the list

You should discover that the order of executions of each of the test methods are not in the same orders and are not independent. It could be useful to empty the list before each test with the method setUp().

So please code and test everything to check tat the model part is working perfectly. Each time, you will add a new feature, consider adding a new test and check there is no regression.

NOTE: setUpBeforeClass() is trigger before starting all test methods, tearDownAfterClass() is trigger after passing all test methods, setUp() is trigger before each test and tearDown() after each test method. Those methods are useful to configure a test by creating a context with data or in the opposite, no data.

4/ Link between Model Part et one view/JSP

At first, create a JSP page to display 4 todo items :

This is an example of code to create Application with data and avoid an empty list. You can note the building of the list is made into the constructor method :

private Application() {
     lesTodos = new ArrayList<Todo>();
     create4TestTodos();
 }
 private void create4TestTodos(){
     addTodo( "Test1" , false );
     addTodo( "Test2" , false );
     addTodo( "Test1actif" , true );
     addTodo( "Test2actif" , true );
 }

Create a JSP page todos.jsp and import the package model into, you will find an example of code to start :

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="main.model.*" %>
Foreach list of todo itemps :
<%
for(Todo todo : Application.getInstance().getLesTodos() ){
%>
<p>
   <%=todo.getTexte() %>
</p>
<%
}
%>

This is very basic JSP to rescue from Application each todo item and display then into <p> tag for learning purpose, of course checkboxes are missing.

Start the JSP as we did into TP 0 to check everything is OK, but it is not a classical way to call directly a JSP with MVC design pattern

NOTE, you can create an index.jsp with auto redirection to call the futur Control Servlet:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    response.sendRedirect("./Control?action=list");
%>

NOTE: to remove 404 error and debug console information on the downloading favinco.ico, you can add this tag to <head> HTML part :

<link rel="icon" href="data:,">

5/ Servlet as the Control part of design pattern MVC

Calling JSP pages as a spaghetti chain of application make web application complex to improve and debug. We will use the idea of state transition diagram instead direct calling from one JSP to an other.

Suppose un application to display email, the call from the list of emails to a detail of one email should be with MVC design pattern with an intermediary call to Servlet Control :

The URL to the Servlet pass one parameter call action to ask the controller if it is possible to transit to detail-email.jsp page with an additional parameter to identify the email :

Why using a controller, because we can load information, check information, logs the transit and even redirect to a different page according to routing requirement of our web application.

Create Servlet by right-clicking on the package control then Menu New > Servlet, please provide the name of the Servlet Class, check the java package if necessary and check also the URL mappings /Control and click button Finish

IMPORTANT NOTE: the mapping is the URL routing information if Tomcat find into URL /Control it will call the doGet() or doPost() method of this Servlet Class.

It is possible d’add several mapping et event use joker mapping as for example *.pdf to call a Servlet on every .pdf URL.

It is also classical to create a new servlet class as Control2 and change only the mapping to make an evolution on the web application.

We will modify the doGet() method with this piece of code :

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

String vueFinale = "todos.jsp";

// TODO: a future doAction() method will be call from here to choose which JSP page to display  
     
request.getRequestDispatcher(vueFinale).forward(request, response);

}

The purpose of vueFinale variable is to store the final JSP name as view to display using the getRequestDispatcher. We create route from information receive from doGet() parameters and the redirection will ne manage into this place.

We can image maybe display an error.jsp page if the program needs to route the user to an error page.

Into the Control class we will code a method call doAction() with request parameters and mainly the parameter action. Using the value of this parameter action, the code will check informations receive from GET/POST forms, manage operations on the model classes and return the value for the next JSP page to display.

private String doAction(HttpServletRequest request) {

  String vueFinale = "erreur.jsp";

   String action = request.getParameter("action");

   // Action1 addTodo
   if ("addTodo".equals(action)) {

       String texte = request.getParameter("todo_texte");
       Application.getInstance().addTodo(texte, false);

       vueFinale = "todos.jsp";
    }

     // Action2 Update list ...


    // ... 
    return vueFinale;
}

So calling this URL ./Control?action=addTodo&todo_texte_chocolat should trigger the piece of code to add a new instance of todo into the model. Then the control servlet class redirect the user to display the view todos.jsp listing all the todo items (inclus the new one).

This code is really partial and you should understand it by implement and debug the core of MVC Web application.

NOTE: if you need to rescue a list of parameters name from this kind of URL http://127.0.0.1:8080/Control?nom=jean&prenom=pierre&civilite=Mr as a list [ nom , prenom , civilite ], try :

List<String> keys = Collections.list(request.getParameterNames());

The next step is to develop a JSP and add features to the servlet to present a todo item list, un HTML horizontal bar (with tag <hr />) and un form to add new todo as :

NOTE: You should know a checkbox input feald is only trigger if the checkbox is check

You can read the following diagram showing sending data from HTML form, viewing information into the URL (the GET method is wonderful for this feature) , then data are send to the Servlet with the submit button and then you should debug the Servlet :

You can open into a separate tab this image to understand links between the HTML form and then Servlet variables.

Add a form to update the checkbox status if some todos are checked or not :

To create n HTML list please use this HTML :

<ul>
<li>chocolat</li>
<li>ananas</li>
</ul>

And to give you some code about tags with HTML form :

<form method="get" action="./Control">
<ul>
<li><input type="checkbox" name="checkbox_chocolat" /> chocolat</li>
<li><input type="checkbox" name="checkbox_ananas" /> ananas</li>
</ul>
<!-- missing some part about submit -->
</form>

You should know to tick the checkbox by default you should add an checked attribut as :

<input type="checkbox" name="checkbox_chocolat" checked />

or not checked by default with nothing :

<input type="checkbox" name="checkbox_chocolat"  />

Of course you should code something like this code :

<%
for(Todo todo : Application.getInstance().getLesTodos() ){
%>
<p>
   <%if ( todo.isActif() { %>
      <input type="checkbox" name="checkbox_" checked />
    <% } else { %>
       <input type="checkbox" name="checkbox_" />
    <% } %>
</p>
<%
}
%>

But maybe there is a way to merge the two part of if/else block to simulate a HTML tag construction with a new checked variable ?

Cliquez ici pour afficher une proposition de solution pour gérer checked:

6/ New controller action: update todo

Usually, it is better to try to code your own personal way to update todo status. Please, consider only as basic structure and make your own version.

We can image 3 different strategies with the HTML part :

  • First is to consider a form for a whole list of todo items and a separate form to add new todo :
<form method="get" action="./Control"> 
<ul> 
   <li>
      <input type="checkbox" name="checkbox_chocolat" /> 
      chocolat 
   </li> 
   <li>
     <input type="checkbox" name="checkbox_ananas" /> 
      ananas
    </li> 
 </ul> 
 <input type="submit" name="action" value="Update list" /> 
</form>

<hr />
<form method="get" action="./Control"> 
   New Todo: <input type="text" name="todo_texte" />
   <input type="submit" name="action" value="Add todo" />
 </form>
  • The second solution is also possible to use a form for each item list
<form method="get" action="./Control">
<ul>
  <li>
   input type="checkbox" name="checkbox_chocolat" /> 
   chocolat 
   <input type="submit" name="action" value="Update liste" /> 
  </li>
</ul>
</form>

<form method="get" action="./Control">
<ul>
  <li>
   input type="checkbox" name="checkbox_ananas" /> 
   chocolat 
   <input type="submit" name="action" value="Update liste" /> 
  </li>
</ul>
</form>

<hr />
<form method="get" action="./Control"> 
   New Todo: <input type="text" name="todo_texte" />
   <input type="submit" name="action" value="Add todo" />
 </form>
  • A third choice is to create a hyperlink to simulate the form to update status
<ul> 
   <li>
      <input type="checkbox" name="checkbox_chocolat" /> 
      chocolat
      <a href="./Control?action=Update%20liste&checkbox_chocolat=on">update</a>
   </li> 
   <li>
     <input type="checkbox" name="checkbox_ananas" /> 
      ananas
      <a href="./Control?action=Update%20liste&checkbox_ananas=on">update</a>
    </li> 
 </ul> 
 <input type="submit" name="action" value="Update list" /> 

Any kind of solution is valid, some are easier to maintain in time.

Server side with the servlet, the action part code Update list, I recommend you to think about uncheck all the todo items then update the list of items send by the form as this way :

if ( "Update list".equals( action ) ){
  // TODO: you should create this function is needed and the Junit test
   Application.getInstance().uncheckAll(); 
   List<String> keys = Collections.list(request.getParameterNames());   
   for(String key: keys) { 
      if ( key.startsWith("checkbox_")) { 
          String todoTexte = key.replace("checkbox_", "");      
          Application.getInstance().updateTodo(todoTexte, true); 
       } 
    } 
}

By the way why this line of code should be better than the second one :

if ( "Update list".equals( action ) ){

// Or 

if ( action.equals( "Update list" ) ){

You should also improve your code with this version :

if ( "Update list".equals( action ) ){ 
   // TODO: create a method to invalid the todo items and then update according parameters
   Application.getInstance().updateListTodo( Collections.list(request.getParameterNames() ); 
}

But it is more important for me to first extract list of parameter into the Servlet and give to Application only verified data. It is just a way of thinking, not a mandatory way of coding.

Another way to improve is to change the checkbox name as :

<form method="get" action="./Control">
<ul>
  <li>
     <input type="checkbox" name="todo" value="chocolat" />
     chocolat
   </li>
   <li>
      <input type="checkbox" name="todo" value="ananas" />
       ananas
    </li>

  <input type="submit" name="action" value="Update list" />
</form>

The URL created by the form submit action will be

http://127.0.0.1:8080/DevWeb/Control&todo=chocolat&todo=ananas&action=Update list

You should rescue the whole list of checkbox parameters with GetParametValues() as :

String[] valuesCheckboxTodo = request.getParameterValues("todo");

7/ Delete todo item

Please provide the last action to delete and item and delivery the code by email. It is not and evaluation, just a milestone of the project before go on.

8/ Add action JSON

Could you add a new action on the controller as the action=json to create a different JSP page not into HTML but in a format exchange to another program.

By the past, we use XML format as this way :

<?xml version="1.0" encoding="utf-8"?> 
  <todos> 
    <todo id="1" texte="chocolat" actif="false" /> 
    <todo id="2" texte="ananas" actif="true" /> 
    <todo id="3" texte="kiwi" actif="false" /> 
  </todos>

But this format is less and less used despite the JSON format :

{ 
 "todos": 
  [ 
   { 
      "id": "1", 
      "texte": "chocolat", 
      "actif": "false" 
    },
   { 
      "id": "2", 
      "texte": "ananas",
      "actif": "true" 
    }, 
    { 
       "id": "3", 
       "texte": "kiwi",
       "actif": "false" 
     }
   ]
 }

This format is also used with JavaScript code to communicate with the web server with AJAX request.

Please code the JSP page and change the content type from text/html to :

<%@ page language="java" contentType="application/json; charset=UTF-8" pageEncoding="UTF-8"%>

You can use an online tool to check JSON format as Online JSON Viewer. Some browser could reject JSON file using single quote instead of double quote or extra coma.

The evolution of the project will create more and more action values to check. It will be wize to split the main controler into several differents servlet controler. All actions based on JSON content return could then be put together into one different controler.

9/ Optional: write a client to use your JSON as an API Restful service

You can develop a Java (or if you like a Python) client program (called a desktop client program or a rich client) to rescue the data via JSON. This program is a simple Java project to develop independently as the Dev Web Tomcat project.

This program is as a rich client provide by OneDrive/DropBox/GoogleDrive/etc. whih call the API to receive only data. We can also use wget/curl command to simulate access to an API with and HTTP GET request.

We can also imagine an IOS/Android application which make HTTP GET request and receive JSON list of items from your DevWeb application.

In Java, we can use one of many libraries to request a JSON and create instances (Google Gson, Jackson, Json-Lib, etc.). I find easier to use json-simple from https://cliftonlabs.github.io/json-simple/, download the JAR from the website and add it to the project (json-simple-4.0.1.jar is copy into a lib folder) :

First step if to create a valid URL for our JSON page

HttpURLConnection urlConnection = null;
try {
     URL url = new URL("http://localhost:8080/DevWeb/json.jsp");
     urlConnection = (HttpURLConnection) url.openConnection();
} catch (MalformedURLException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
}

Then a script to read line and regroup them into a stringBuilder variable :

StringBuilder stringBuilder = new StringBuilder();
if (urlConnection != null) {
  try (
     BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) 
     {
          String line;
          while ((line = reader.readLine()) != null) {
               stringBuilder.append(line);
          }
      }catch (IOException e) {
           e.printStackTrace();
      }
}

At least, we will use json-simple JAR classes to parse JSON node elements and create Todo new instance :

JsonObject  deserializedObject = Jsoner.deserialize(stringBuilder.toString(), new JsonObject());		

JsonArray todos = (JsonArray) deserializedObject.get("todos");

for(int i=0; i < todos.size(); i ++) {
   JsonObject todo = (JsonObject) todos.get(i);
   String texte = (String) todo.get("texte");
    boolean actif = ( "true".equalsIgnoreCase( todo.get("actif").toString() )); 
    Todo newTodo = new Todo( texte , actif );
}
			

This way is far from very verbose way to code, just to have a view of serialization/deserialization of instance, but other libraries hide all the complexity make the code more readable.

10/ Optional: using a JSP Tag

To be clear, this is a new template language named ‘Expression Language’ or EL. This language use a simple expression to call getters and setters as {todo.texte} to call todo.getTexte().

Suppose we want to improve the item todo part of the JSP page managing the checkbox and the text display into the <il> HTML tag.

First create a folder WebContent/WEB-INF/tags/, then create a new file « JSP tag » named todo.tag as :

The content of todo.tag will be a short part of the HTML/JSP :

<%@tag language="java" pageEncoding="ISO-8859-1"%>
<%@tag import="main.model.Todo" %>
<%@attribute name="todo" required="true" type="main.model.Todo"  %>

<li>
	<input type="checkbox" name="todo_${todo.texte}" value="${todo.texte}"/> 
${todo.texte}   
		
</li>

A todo item is required to use this JSP Tag is the type main.model.Todo is import into the JSP Tag.

Return to the todos.jsp listing item todo, add the import of the JSP tag with :

<%@taglib prefix="projetDevWeb" tagdir="/WEB-INF/tags" %>

Using a prefix is a way to avoid tag name conflicts if you import many tags, the inside you loop on all item todo, you should call the tag with the variable storing item todo information :

<projetDevWeb:todo todo="${currentTodo}" > </projetDevWeb:todo>

But the variable currentTodo must be backup explicitely into the page context (or into the session context if you want to), because the execution content of the JSP tag is different than the contexte of the JSP page. Variables create into the JSP page are not visible by default into the JSP tag to avoid conflict. So adding this liste will create a variable stored into the context page :

pageContext.setAttribute("currentTodo", todo , PageContext.PAGE_SCOPE);

Our final code should be close to this example :

<%
for(Todo todo : Application.getInstance().getLesTodos()){	
   pageContext.setAttribute("currentTodo", todo , PageContext.PAGE_SCOPE);
   %>
        <projetDevWeb:todo todo="${currentTodo}" >
	</projetDevWeb:todo>
   <%
}
%>

You have to understand that the EL language use the coding way ${instance.property} as a simple way to call getters and setters. This simple version of using taglib and JSTL is really basic way to divide the rendering of the HTML page into several sub files.

One more advanced way to use EL language is to add JSTL libraries to Tomcat 9 : jakarta.servlet.jsp.jstl-1.2.6.jar et jakarta.servlet.jsp.jstl-api-1.2.7.jar

Then you can add a new tags’ library by default by add this line of code at the beginning of your JSP page :

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

The using the foreach JSTL tag to iterate on the application list of todo items :

<c:forEach 
    items="${Application.getInstance().getLesTodos()}" 
    var="todo" >  	
    	<projetDevWeb:todo todo="${todo}" > </projetDevWeb:todo> 
</c:forEach>   

Using Application singleton allow us to work with the variable into the JSP context page and into the JSP tag.

Publié dans IMT Mines Alès | Laisser un commentaire

Web Development TP 2

1/ Add a CSS style sheet

With Eclipse, add a new folder css into the folder webapp as (the screenshot show WebContent folder which was the past name of webapp folder) :

Menu New > Other then filter the very long list file with css then choose CSS file. Then create a style.css file with the content below :

div#central{
  position:absolute;
  left: 50%;
  top: 10%;
  width: 800px;
  height: 800px;
  margin-top: -50px;
  margin-left: -400px;
  color: black;
  background-color:rgb(200,220,200);
  padding: 20px;
}
ul {
  list-style: none;
  margin: 0;
  padding: 4px 4px 4px 4px;
}
ul > li{
   display: inline;
}
div#menu{
  position:relative;
  left:10%;
  width:80%;
  background-color:rgb(200,240,220);
}

To use this css your code should containts 2 tag div with « id » as central and another « id » as menu. Consider include the div menu inside the div central and add the link between your JSP and the style.css into the <head> tag :

<link rel="stylesheet" type="text/css" href="css/style.css">
<div id="central">
 <div id="menu">
      <!-- Menu area -->
 </div>

    <!-- Content area -->
</div>

Then we want to use a CSS rule to put with an uppercase first letter for our list of todo element:

<li> 
<input type="checkbox" name="checkbox_lait" /> butter
</li>

The css rule will be :

li { text-transform: capitalize; }

You can test it by select the text near the checkbox, then « inspect » to display the HTML content on the Dev Web tools on the right. Then the small plus bouton could help to create a new rule. We can see the HTML text is not capitalize, but the display will be with a first capital letter :

2/ Area menu

Into the menu area, we will use a list of hyperlink to present a menu, consult the website alsacreation to create step by step a simple css menu. Please stop before using graphic menu with rollover and without javascript).

Our purpose here is to add a simple menu with some CSS features include the modification of a simple list tag element :

<ul><li><a href="#">Menu 1</a></li><li><a href="#">Menu 2</a></li></ul>

After the creation of the menu with the CSS style, place de code into a div menu as the image below shows.

Please change colors and design with CSS, it is definitely ugly to let your change as your witch.

To understand the organization between div and other HTML tag, please use the inspector include into Dev Web tools of your browser.

You can inspect the website www.mines-ales.fr, open dev web tools and follow steps as you see below or you can right-click on un HTML element and Menu > Inspector :

On the right part of Inspector, you can see CSS rules and test adding some new CSS. On a local website, you can use Chrome/Chromium with option to save directly your css modification with –user-data-dir switch on the browser command line (see TP 0).

You can create a basic menu with hyperlink to call your application controller as this way :

<ul>
  <li>
   <a href="./Controlaction=pageAddTodo">Add Todo</a>
  </li>
  <li>
      <a href="./Control?action=xml">Liste xml</a>
  </li>
  <li>
    <a href="./Control?action=json">Liste Json</a>
  </li>
</ul>

This form to create a menu is a very HTML way to avoid inject Javascript as we will do later.

3/ First step into Boostrap CSS framework

As start, we will use a so classical Boostrap template named Jumbotron. It is a classical top menu with a central area for title/small text paragraph/one button, then a line with 3 columns of combined title/paragraph/button and a footnote.

To understand the way Boostrap is degin, think about one line with a left area of 1/3 of the width (in green) and a second area same line but 2/3 of the width (in blue) :

<div class="row">
    <div class="col-md-3" style="background-color:green;padding:50px;">
             Left green area
     </div>

     <div class="col-md-9" style="background-color:blue;padding:50px;color:white">
             Right blue area
     </div>
</div>

The purpose of the next step is to rescue the Jumbotron and place our todo items list into the left column.

At first study with Inspector tool the HTML structure and decte the div which manage the left area. That should be a tag as below :

<div class="col-md-4"> 

We should think adding an ID attribute to this tag in the future to identify easily this important DIV.

To copy HTML just right-click on the HTML page and display HTML, select all, copy and paste. Or Open Tab Network with Dev Web Tools, select CSS and JS elements and choose to save each CSS/JS files :

NOTE: Firefox do not save, so instead open into a separate tab and save each element. You don’t need e10-viewport-bug-workaround CSS or JS, we don’t need to support Internet Explorer 10 by now.

4/ Using logs

Using logs is one skill to manage 2 classical problems :

  • I want several levels of display technical information, for example at least INFO and CRITICAL
  • I want several sources and destination of technical information, for example: store information into files, send information to the console, send information to an external server.

A rookie in computer science usualy tend to write code with output to the console :

System.out.println("Error " + e);

This way to work with Tomcat will work, but all output will go into a file named catalina.out even if your web server as 10 different applications into one single file. A mess event if you use the second output System.err.println.

Thinking an application in production mode, you should want to store only critical information at the opposite in development mode, you should want verbose log.

Log4J is a Log framework tool managing several destination to logs (console and/or files and/or database and/or dedicated log server). We could start a program with a certain log level and even change it by program.

To install log4j, just download my library version log4j-1.2.17.jar (very simple to learn) and place it into sub folder lib (to create if not exist) into WEB-INF folder (inside webapp folder).

Add the new jar to the build path by right click on the jar Menu Build Path > Add to Build Path :

NOTE: we can add many jar libraries to deploy with our web project so each web application store its specifics jars independently on another dev web project as you see below :

NOTE: you should also use a tomcat specific lib folder to store libraries in common for all dev web projects on the Tomcat web server. The strategic is always to choose to fix a specific library for all the project to have a standard version, or in the opposite to let project autonomous. That a strategic in production decision.

To configure log4j, we need to create a log4j.properties file into Java Resources > src folder (no need package, this is not a java file just a configuration file). Create a new file, righ click on the folder New > Other …> General > Untitled Text File.

Fill the file with information to output logs to the console and to a file store into a folder created by you into the Dev Web project (C:/DEV/workspace/DevWeb/logs/)

log4j.rootLogger=DEBUG,stdout,file

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n


log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=C:/DEV/workspace/DevWeb/logs/out.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n

NOTE: we will use a folder available to Eclipse after Refresh (F5 key) to make it simple to see new content, but it is more common to place files outside the computer on a separate drive.

NOTE2: if you find any troubles that Tomcat not found any appenders (WARNING: No appenders could be found for logger) into the console. You could copy the log4j.properties into the following folder : src/main/webapp/WEB-INF/classes/.

The first line is to set the log level to DEBUG and there are 2 loggers: stdout and file (named as you want but do not forget to change everywhere). We can later add more loggers to a database, a log server, emails, log rotation, etc.

Each line starting by log4j.appender.stdout sets settings for a logger which display information into the console as a System.out.println() did.

Each line starting by log4j.appender.file sets settings for a log file so the log file name and the pattern form of each line as :

Date: %d{ABSOLUTE}
Log level: %5p
Logger name: %c{1}
Log line number: %L
Message: %m

More pattern settings for log4j

Now to use a logger into a class, we will create a log instance as a property of you class :

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("DevWebProject");

NOTE: I use the absolute name of the class Logger (org.apache.log4j) because Tomcat include others log framework (org.apache.commons.logging) for internal purpose and it could create conflict. Here is an example of strength/weakness of Java with several solutions for the feature of logging system, but the variety of framework create multiples situations not so easy to manage. At this opposite, the competition between framework create synergy to make better product.

Now, to log an information, we can call instance with the level of severity. There are usually 6 levels, from the most critical to the lowest :

  1. fatal
  2. error
  3. warm
  4. info
  5. debug
  6. trace

If the log4j properties file set the log level to info, logs messages at level fatal, error, warm and info will be sent.

Keep in mind to set the level accorded to the importance as explain it in this article: https://dzone.com/articles/logging-best-practices

As an example, if I ant to log a new created todo item, level will be very low debug level because in production I do not want this level of information.

// Action1 addTodo 
if ("addTodo".equals(action)) { 
  logger.debug( "addTodo " + texte );
}

Or this pattern way as exxample by Setu Patani in his article :

// Action1 addTodo 
if ("addTodo".equals(action)) { 
  logger.debug( String.format( "addTodo %s", texte ) );
}

Log4j new version accept pattern as this form :

// Action1 addTodo 
if ("addTodo".equals(action)) { 
  logger.debug( "addTodo {}", texte );
}

Now we can create messages with the log level according to the criticizes:

logger.trace("Very not important message");
logger.debug("May be useful in debug mode");
logger.info("Classical message level");
logger.warm("Just warning, but the code should not stop");
logger.error("Classical error level");
logger.fatal("Very important error");

So code several logs messages into your program and make it work to create many logs. Check console and the log file (Refresh folder with F5 key in Eclipse to update folder content)

The first line of log4j.properties file set the minimum error level :

log4j.rootLogger=DEBUG // display FATAL,ERROR,WARM, INFO et DEBUG

or

log4j.rootLogger=ERROR// display FATAL et ERROR

Into the program, I can change the level as I wish :

log.setLevel( org.apache.log4j.Level.INFO );

Now add a tird logger to display HTML report logs, with a new log :

log4j.appender.html=org.apache.log4j.DailyRollingFileAppender
log4j.appender.html.DatePattern='.'yyyy-MM-dd-HH-mm
log4j.appender.html.layout=org.apache.log4j.HTMLLayout
log4j.appender.HTML.layout.LocationInfo=true
log4j.appender.HTML.layout.Title=Application logs
log4j.appender.html.File=C:/Dev/workspace/logs/application.html

Do not forget to add it on the first line of log4j.properties and start again your web application to create new logs messages.

This logger will create an independent HTML file according to the date format. We can also create a Rolling file with a separate level call requete with a max log file and a max number of rolling log files with :

log4j.rootLogger=DEBUG,stdout, file
log4j.logger.requete=INFO, requete

log4j.appender.requete=org.apache.log4j.RollingFileAppender
log4j.appender.requete.File=c:/Dev/workspace/DevWeb/logs/requete.log log4j.appender.requete.layout=org.apache.log4j.PatternLayout 
log4j.appender.requete.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n
log4j.appender.requete.MaxFileSize=10KB
log4j.appender.requete.MaxBackupIndex=5

This log could be use to log only SQL request but limit the number of file to preserve a certain amount of logs. This way several files requetes.log.X will be created until 10Kb for one file. After 5 files created, the first one will be deleted to store new logs.

5/ Install small plugin Eclipse Log Viewer

To display logs, you can use a small Eclipse plugin call Log Viewer. Just drag and drop the « Install » button into Eclipse to popup the windows to confirm installation (acceptation of license, acceptation of certificate, etc.)

Then you can display into your Eclipse J2EE perspective this new plugin via Menu Windows > Show View > Other… and search Log Viewer :

At the top right of Log Viewer panel, you can open log file, chose colorization, refresh display, etc.

At first, open a log file newly created, press Open Logfile button :

Then you can apply rules to display element with Show rules preferences:

So then we can set if word INFO, display background color is green, if word is ERROR, background color should be red :

You can display your log to follow the most critical part.

6/ Helper Class

Design pattern Helper is a concept of a « helping class ». As an example, suppose a class Book storing classical information about a book (the term used POJO: Plain-Old Java Object). Instances of book purpose is to store properties (title, page number, author, editor, ISBN, Series name, etc.).

Suppose we want to code several methods to check information as a control of ISBN value, we could imagine create a checkISBN() and checkAuthor() methods into a separate class named BookHelper to avoid including those methods into the Book class. Think the point Book purpose is to only store and provide properties only with getters and setters. So we need to store technical functions into a separate class.

We can imagine create a utility class to store methods which help to check ISBN and Author but fast this class will be full of methods from other class than Book. So let separate methods for class Book into a class BookHelper.

In our project, we can create a class ControlHelper to store method to help Control to log parameters pass to Control class :

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger( "BoostrapSample.main.ControlerHelper" );

public static void logAllParameters(HttpServletRequest request){

 Map<String, String[]> parameters = request.getParameterMap();
 for(String parameter : parameters.keySet()) { 
    String[] values = parameters.get(parameter);
    String value = Arrays.stream( values ).collect(Collectors.joining(","));

    log.info( "Parametre " + parameter + " " + value ); 
 }

}

Into this method, we use a « new » feature from Java called stream. Streams are a modern way to speed up classical list data processing. Serialization of data processing with stream could be execute on list structures as classes/interfaces Set, List, ArrayList, Map, Array, Collection, etc.

To convert an « old » String[] values into a stream to speed up data processing and create more visible chain of treatment with inline method :

Arrays.stream( values )

NOTE: using inline method is also used in Javascript as we see later

Calling an inline method or anonymous is a programming technic to create an instance and call a method in one line. Suppose we want to code a new call to action method on a button into a graphical interface :

Button b=new Button("Click Here"); 

b.addActionListener(
   new ActionListener(){ 
        public void actionPerformed(ActionEvent e){ 
            System.out.println("Hello World!"); 
    } 
});

In this case the class ActionListerner only purpose is to execute one unique method actionPerformed. The inline version with Java lamba solution should be more visible :

b.addActionListener( e  -> System.out.println("Hello World!"));

The simplification is obvious and time to time called syntaxes sugar to symbolize as easy you could read this line of code.

Into our application, we will use a stream onto our lesTodos list :

lesTodos.stream()

Now we want to use a filter method to return only todos items with actif true value. The symbol -> use at left what is the parameter name on each stream element, then it will apply the method on each right part :

todo -> todo.isActif()

You can compare with the anonymous version :

Class anonymous{
   public boolean method_call_by-default(Todo todo){
       return todo.isActif();
   }
}

So combine previous part, the stream will be :

lesTodos.stream().filter( todo -> todo.isActif())

This feature, mainly used with Data mining and Big Data, is to combine and chain operation to use JVM parallelization capabilities.

Combine todo to rescue only texte of todo actif will be :

lesTodos.stream().filter( todo -> todo.isActif()).map( todo -> todo.getTexte() )

We can then combien and merge data with a separator symbol en transform the final result into a String with :

String reponse = lesTodos.stream().filter( todo -> todo.isActif()).map( todo -> todo.getTexte() ).collect(Collectors.joining(","));

Online, you will find many samples using streams to work, Oracle website shows a sum of integers as a good example.

7/ Conditional debug breakpoint

A common feature with modern IDE is to create a conditional debug breakpoint. Right click in Eclipse at the left of line number into the source code interface et select into the Menu « Breakpoint Properties…« , then you can tick « Conditional« , « Suspend when true » :

Using conditional breakpoint while debug is a way to speed up development. Time to time I debug from the beginning line by line to understand a process, later it will be more valuable to only debug into a certain case. Try it…

8/ Database part

To use a database we will add a JDBC connector linking our Java code to this database. You can use a Mysql JDBC connector if you want to use an already install Mysql server. I use Mysql regulary but for a training course, to manage security, you should consider using a simple Sqlite database.

Using Sqlite with Java is just adding a new JAR sqlite-jdbc-3.8.11.2.jar (or if broken here) into lib directory and create into dao package a new DaoManager class.

The folowing code is an partial example of a singleton DaoManager class, you should improve it with your previous code write until now.

public class DaoManager {
  private DaoManager() {
    try {
      Class.forName("org.sqlite.JDBC");
      connection = DriverManager.getConnection("jdbc:sqlite:c:/DEV/Workspace/todo.db");
     } catch (Exception e) {
      log.severe( String.format( "Sqlite error %s" , e.getMessage() ) );
      }
     log.info("Opened database successfully");

   createDatabase();
  } 


  private void createDatabase() {
    try {
      Statement stmt = connection.createStatement();
      String sql = "CREATE TABLE IF NOT EXISTS TODO ( ID INTEGER PRIMARY KEY AUTOINCREMENT, TEXTE TEXT NOT NULL, ACTIF BOOLEAN NOT NULL)";

      stmt.executeUpdate(sql);
      stmt.close();
     } catch (Exception e) {
       log.severe( e.getClass().getName() + ": " + e.getMessage() );
     }
    addTodo( new Todo("ananas" , false ) );
    addTodo( new Todo("chocolat" , false ) );
  }

public void addTodo(Todo todo){

  try {
    PreparedStatement preparedStatment = connection.prepareStatement("insert into TODO(TEXTE,ACTIF) values( ? , ? )" );

    preparedStatment.setString(1, todo.getTexte() );
    preparedStatment.setBoolean(2, todo.isActif() );

    preparedStatment.execute();
    preparedStatment.close();

  } catch (Exception e) {
     log.severe( e.getClass().getName() + ": " + e.getMessage() );
   }
}

public List<Todo> getAllTodo(){
   List<Todo> returnListTodo = new ArrayList<Todo>();
   try {
      Statement statement = connection.createStatement();

      if ( statement.execute( "Select TEXTE,ACTIF FROM TODO " ) ){
        ResultSet resultSet = statement.getResultSet();
        while ( resultSet.next() ) {
          String texte = resultSet.getString("TEXTE");
          boolean actif = resultSet.getBoolean("ACTIF");

          returnListTodo.add( new Todo( texte , actif ));
        }
       }
       statement.close();

    } catch (Exception e) {
        log.severe( e.getClass().getName() + ": " + e.getMessage() );
    }
     return returnListTodo 
  }

}

There are 2 strategies to call DaoManager singleton, one from the Control class and one from the Application. In my mind, I think more logical to call DaoManager from Control class with « have the hand  » over Application class and DaoManager to do the job.

After calling DaoManager, you should create the database sqlite file c:/DEV/Workspace/todo.db , to check content and structure, I think https://sqlitebrowser.org/dl/ tool it is perfect to open and manage database as phpMyAdmin does for Mysql.

The file c:/DEV/Workspace/todo.db storing the database is locked if you open it with Sqlitebrowser so close the access before restart your web application.

Install Sqlite with DB Browser Desktop check :

Then start DBBrowser and open c:/DEV/Workspace/todo.db :

You can browse your data as you wish :

You can use this tool to check todo items are stored into the database. We will load the list of todo items each time Control class is called. There are solutions to avoid calling on each HTTP request, but at start we are close as standard 3-tiers architectures.

Now there are an important modification of your application. Add a new property call id (of type int) to your Todo class. This id manage a unique identification number for your todo item.

DaoManager should create a table Todo with an auto increment column ID. The database will generate this unique ID et your code should rescue it with a method call getGeneratedKeys() after an SQL command INSERT INTO… :

ResultSet rs = preparedStatment.getGeneratedKeys();
if (rs.next()) {
   autoGeneratedIdFromDatabase = rs.getInt(1);
   todo.setId( autoGeneratedIdFromDatabase );
} else {
 logger.error( String.format("Error exception %s ", ex.getMessage() ) );
}

Now you can use this new ID value to manage your todo for update/delete everywhere into your application. An important refactoring work to check you can manage this evolution of the project.

9/ Optionnal: logs message into the database

Change settings bellow to link log4j to sqllite database file and do not forget to create the new table.

log4j.rootLogger=DEBUG, DB

# Configuration de l'appendice JDBC
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:sqlite:votre_base_de_donnees.db
log4j.appender.DB.driver=org.sqlite.JDBC
log4j.appender.DB.user=
log4j.appender.DB.password=

# Requête SQL pour insérer les logs
log4j.appender.DB.sql=INSERT INTO logs (timestamp, level, logger, message) VALUES ('%d{yyyy-MM-dd HH:mm:ss}', '%p', '%c', '%m')

# Mise en correspondance des colonnes de la table de logs
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
log4j.appender.DB.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %c: %m%n

It will be more common to have a different server to store log usualy a NoSql database.

SQL :

CREATE TABLE logs (
id INT IDENTITY(1,1) PRIMARY KEY,
timestamp VARCHAR(255),
level VARCHAR(50),
logger VARCHAR(255),
message TEXT
);
Publié dans IMT Mines Alès | Laisser un commentaire

Web Development TP 0

At first, you can download slides from Web Development course with detailed explanations of Servlet/JSP development in MVC. Do not hesitate to read it often to remind features.

Development tools and software are free and/or open source. Tomcat 9 and Eclipse J2EE are provide regarding of your OS on this website for speed up download http://www.dev.lgi2p.mines-ales.fr/install/, but you can download online anyway :

TP 0 Installation Eclipse and Tomcat to adapt regards your OS and specific configuration

Please at first install an Oracle Java JDK version 21 for compatibility purpose, and check the folder where installation is done. JDK update process could also change the folder path.

If needed, look on your computer to find a software call javac.exe or javac to be sure to find a Java JDK not the Java JRE. The Java JRE is not design to manage Tomcat, and errors will be find late into the process. So best to check and write down the path to a full standard Oracle Java JDK.

Download and unzip Apache Tomcat 9 core version into a subfolder without space or not classical characters as accents or special characters. Usually with Windows OS, I am please to find a folder call c:\Developpement or c:\DEV to easy managed software programs. With Tomcat is common to unzip C:\DEV\apache-tomcat-9.0.75\ (but it is better to avoid C:\DEV\apache-tomcat-9.0.75\apache-tomcat-9.0.75\)

Download and unzip the Eclipse IDE for Enterprise Java and Web Development, later called Eclipse J2EE into a specific folder without space or not classical characters as accents or special characters. Usually with Windows OS, I am please to find a folder call c:\Developpement or c:\DEV to easy managed software programs. I usually unzip everything into C:\DEV\eclipse-jee-2023-12-R-win32-x86_64\ (but it is better to avoid C:\DEV\eclipse-jee-2023-12-R-win32-x86_64\eclipse\)

NOTE: don’t use another Eclipse software provide by another courses, Eclipse Plugins could be in conflict and version of settings could lead to troubles.

Start Eclipse with eclipse.exe or eclipse program to answer firsts settings as bellow :

  • The folder Worskspace (as Windows path C:\DEV\Workspace) will store all settings and projects, so it is important to backup this place regularly.
  • Tick « Use this as the default and do not ask again » prevent Eclipse to popup this dialog each time Eclipse start. You can switch Workspace in case with Menu File > Switch Workspace.

You can then close the « Welcome » tab windows, not really useful at this moment.

The next step is to remove the default Java JRE from Eclipse J2EE and provide our Oracle Java JDK. Technically, Eclipse J2EE could manage several Java versions but we will keep simple with only one JDK.

  • Menu « Windows » > « Preferences » > « Java » > « Installed JREs »
  • Press buton « Add » to provide « Standard VM » with « Installed JRE Home directory is the full path of the initial Oracle Java JDK noted at the first step.
  • Remove previous JDK to be sure that Oracle Java JDK is the default one.
The default and unique Oracle Java JDK provide

Eclipse IDE provide several tabs organizations call perspectives. We will use mainly Java EE perspective and Debug Perspective. Please use Menu « Window » > « Open Perspective »> > »Other » and activate « Java EE » perspective (top right button).

Java EE Perspective is the only perspective with « Server » Tab so if you do not find this tab please switch perspective or right click on « Java EE » perspective button to reset this perspective to its initial configuration.

Then click on « No servers are available. Click this link to create a new server »

The first step is to choose the « Tomcat 9 Server » version

Please provide, the full path to find the Apache Tomcat previously download and unzip as below. I like to choose the correct JDK installed with the previous step to be informed by Eclipse if any update change the JDK provide by default:

On tab « Server » right click to open the menu and start in Debug Mode this Apache Tomcat server from Eclipse.

On Windows, the firewall dialog should be open to ask you the authorization to give access to the network to Java and Eclipse, so please answer yes.

Open « Console » tab to consult all output from Tomcat server, the last sentence should be « The server startup took [xxx] milliseconds » to inform you the configuration is correct.

To confirm, please open a web browser and consult http://127.0.0.1:8080/ , you could be surprise by :8080, the default settings for Tomcat in development is to listen the 8080 port instead the default http port 80 or the default https port 443.

The front page will be 404 page because no content will be at present deploy by Tomcat but this page with « Apache Tomcat/9.0.75 » shows everything is fine just there is no content:

So now, we will create a new project to deploy content into Tomcat. With Eclipse, use Menu File > New > Other > Web > Dynamic Web Project then provide a Project Name without space or specific characters as accents. DevWeb will be ok and press finish button. Then you have to add this project to our fresh new Tomcat server.

With the « Server » tab, right clic on the Tomcat Server and select « Add and Remove », with the new dialog windows, press « Add all>> » to add this project then « Finish » button :

Tomcat will automatically deploy the Dev Web project on Tomcat Server. So now download the IMT Mines Ales logo PNG image (https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/IMT_Mines_Al%C3%A8s.svg/640px-IMT_Mines_Al%C3%A8s.svg.png) into the desktop.

You can drag and drop the image from the desktop to the src/main/webapp folder and choose « Copy files » or you can place the image into the disk at C:\DEV\Workspace\DevWeb\src\main\webapp\ but after you have to « Refresh » the project by pressing F5 key :

Now try to correct the URL http://127.0.0.1:8080/ by adding the project name and the image filename to display this image into the browser. The default form should be « http://127.0.0.1:8080/DevWeb/<image_name>.png »

By default, some Web server could display the content of the folder, but the default configuration of Tomcat is to hide the folder content.

Now we can add HTML and CSS content from the CSS Zen Garden website, you can download the HTLM file and the CSS file and place those file into the webapp folder. You should restart Tomcat Server to force deployment of file 217.css and « CSS Zen Garden The Beauty of CSS Design.htm » file and consult the URL http://127.0.0.1:8080/DevWeb/CSS%20Zen%20Garden%20The%20Beauty%20of%20CSS%20Design.htm

You can see with the DevWeb tool of Firefox/Chrome Browser (CTRL+ALT+I key) there are trouble with the 211.css file. The Network tab show the browser is not able to download the 211.css file. You have to correct the « CSS Zen Garden The Beauty of CSS Design.htm » file to match the URL.

NOTE: anytime you find %20 is the encoding URL value for space, please correct the HTML file to help the browser to download and apply the stylesheet file. The way to open « Network » tab with DevWeb Tools into the Web Browser is the correct way to look of trouble with Web Development, key this way of working in your mind.

Next step is to create index.jsp page with menu File > New > JSP File, you have to provide the filename as index.jsp and the parent folder should be src/main/webapp by default. Add the content to display number from 0 to 9 :

You can add a title to your page and click on the left of line number to add (or remove if needed) a breakpoint, then click on the source code to open the menu to Debug As > « Debug on Server » then choose « Tomcat 9 server » and check « Alway use this server when running this project » to avoid this step later, then button Finish.

You should have an Eclipse dialog to ask you to switch to the Debug Perspective :

You should check « Remember my decision » and button Switch to prevent this step later.

Eclipse then open the default browser for your OS (we can change easily with Menu Windows > Preferences) and way to debug the JSP at the line marks by the breakpoint. Press F6 key to step over, or F8 key to Resume to the next break point.

You can find more details about Eclipse Debug with « Eclipse debogage et points d’arrets« .

The next step is to create sub folders « css » and « img » to the webapp folder and place contents and find URLs to locate thoses contents.

You can define a default browser as Chromium, with very helpful settings for development only Menu Windows > Preferences, then General > Web Browser

I use options for this specific Chromium browser dedicated to Web Development only :

--disable-web-security --disable-gpu --user-data-dir=c:\DEV\worskpace --auto-open-devtools-for-tabs --remote-debugging-port=9222 --incognito --single-process  "%URL"

  • disable-web-security : allow to open contents from severals web server for Framework development as Node.js and tomcat
  • disable-gpu: desactivation of GPU to test a very basic browser
  • user-data-dir : provide a folder to edit CSS and Javascript from Chromium
  • auto-open-devtools-for-tabs: open DevWeb tools by default
  • remote-debugging-port: remote javascript debug mainly use with Typescript
  • incognito: default incognito browser
  • single-process: limit the CPU usage of this browser enough to do the job
Publié dans IMT Mines Alès | Laisser un commentaire

Formation Python

PYTHON c’est:

  • un  révolver
  • deux films d’horreurs
  • un serpent de la famille des pythonidae et loxocemidae
  • un langage de programmation

 

http://www.python.org

PREMIER TRUC

Python 3.12  ou  Python 2.7.18

Normalement, le python 2.7.xy n’existe que pour assurer le fonctionnement d’anciens programmes. Vous devriez commencer par la branche 3.x.y.

Les différentes sont minimes sur le fond mais pas sur la forme:

Python 2                            Python 3   
print "Bonjour le monde"        →   print("Bonjour le monde")
print "\n".join([x, y])         →   print(x, y, sep="\n")
xrange()                        →   range()
reduce()                        →   functools.reduce()
intern()                        →   sys.intern()
SimpleDialog                    →   tkinter.simpledialog

 


SECOND TRUC

 

macOS 64-bit universal2 installer macOS for macOS 10.9 and later
Windows installer (64-bit) Windows Recommended
Windows installer (ARM64) Windows Experimental

 

A installer dans un dossier :

Il est à noter que :

  • deux versions de python peuvent cohabiter sur le même ordinateur, mais il faut bien sûr dans ce cas gérer correctement la situation pour éviter de s’emmêler
  • un logiciel de développement PyCharm sera installé par la suite pour nous aider à développer
  • Mes fichiers des programmes sont stockés dans un dossier PyCharmProjects mais ils peuvent tout aussi bien être dans « Mes Documents », sur le bureau, dans n’importe quel dossier, etc.
  • Il vaut mieux se souvenir du chemin complet sur le disque dur du programme c:\Developpement\Python312\python.exe (pour Windows par exemple) /usr/bin/python (pour Mac)

 

Installation de python sous Mac OS

Installation de python 3.6.2 sous Mac OS

 


TROISIEME TRUC

Il n’est pas possible de donner un programme Windows par exemple python.exe à un ordinateur sous Mac et vice-et-versa.

Par contre, un programme écrit en langage python peut être envoyé depuis Windows pour être exécuté sur un Mac qui a l’exécutable python installé.

A l’identique de Matalb par exemple, les programmes ne sont pas exécutés directement par le système d’exploitation Windows ou Mac, mais sont exécutés pas un programme tierce python.exe ou matlab.exe (python et matlab sous MacOs) pour s’exécuter.

On appelle ces programmes des scripts et on peut ouvrir le fichier initial avec un simple éditeur de texte (bloc note sous Windows, text edit sous MacOs).

L’option aujourd’hui d’utiliser Vscode en version .zip  puis de créer dans ce dossier un sous-dossier data (ou code-portable-data à côté du dossier dézipé)  comme expliquer dans ce document rend VScode portable simplement.

NOTA : en fait python compile votre fichier.py en pseudo exécutable fichier.pyc qui sera plus rapidement exécuté ensuite s’il n’est pas modifié

On verra aussi comment utiliser l’interpréteur de commandes de python pour taper rapidement des lignes de scripts et voir le résultat.


EXERCICE 1

 

Après une installation réussie de python, fabriquez le fichier exercice1.py avec le contenu suivant :

# Exercice 1
import time

print ( "Je m'affiche 5 secondes " )

time.sleep(5)
# Fin du programme

Pour fabriquer ce fichier, vous pouvez utiliser de nombreux éditeurs. Personnellement, j’en utilise plusieurs selon la situation (tests d’une fonction, gros projets, proof-of-concepts, etc.) et on peut même entrer du python dans le navigateur via des sites comme http://ideone.com/  ou https://www.tutorialspoint.com//execute_python3_online.php.

Le plus simple pour commencer est d’utiliser l’éditeur IDLE qui est fourni par défaut par python :

IDLE proposé par python par défaut pour Windows

Logiciel IDLE proposé par python pour MacOS

Logiciel IDLE proposé par python pour MacOS

Faites Menu File > New File et entrez le code suivant:

# Exercice 1
import time

print ( "Je m'affiche 5 secondes " )

time.sleep(5)
# Fin du programme

Sauvegarder le fichier en exercice1.py dans un dossier dont vous vous souviendrez par exemple dans « Documents ».

Pour exécuter le programme, le plus simple est d’utiliser la touche F5 ou via le menu
Run > Run Module

 

Une autre solution est d’utiliser l’interpréteur de commande python (appelé aussi shell python). Si vous lancez le programme python sans aucune information, c’est une fenêtre avec ce genre d’informations qui va apparaitre pour vous proposer d’entrer les commandes au prompt (le prompt est les symboles >>> avec le curseur qui attend vos commandes):

Python 3.12.2 (v3.12.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Entrer la ligne suivante au clavier en modifiant le chemin pour correspondre aux dossiers où se trouvent votre programme. (NOTA: il faut saisir une simple quote):

exec( open ('c:/Users/pierre.jean/Desktop/Exercice1.py').read() )

Sous Mac par exemple si le fichier exercices1.py se trouve dans le dossier Documents:

exec( open('/Users/pierre.jean/Documents/exercice1.py').read() )

Cette ligne lance le programme exercice1.py directement python dans l’interpréteur de commandes python.

On pourrait ainsi entrer directement les commandes en appuyant sur entrée à chaque bout de ligne. Essayez de modifier le temps d’attente de 5 secondes et le texte affiché:

import time 
print ( "Je m'affiche 5 secondes " ) 
time.sleep(5) 

 

On peut aussi fabriquer un raccourci sous windows qui va appeler python.exe en lui passant notre programme en paramètre. Clic droit sur bureau puis choisir « Nouveau » puis « Raccourci » dans l’emplacement indiquer le chemin vers le programme python suivi du nom du programme, par exemple (notez l’espace entre les .exe et le chemin du fichier exercice1.py):

c:\Developpement\Python3.11\python.exe c:\User\pierre.jean\Documents\exercice1.py

 

Sous MacOs, cette solution  semble être la plus simple:

Faire click droit sur le fichier python et choisir « Python Launcher ».

 

 

 


QUATRIÈME TRUC

 

Utilisation de l’interpréteur pour tester quelques commandes et afficher des variables pour tester rapidement :

Python 3.12.2 (v3.12.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>notes = [ 10 , 15 ,8 , 6]
>>>print ( notes )
[10, 15, 8, 6]
>>>notes 
[10, 15, 8, 6]
>>> print ( notes [ 2 ] )
8
>>> print ( notes [ 2:4 ] )
[8, 6]
>>> print ( notes [ :3 ] )
[10, 15, 8]
>>>print ( notes [ 1: ] )
[15, 8, 6]
>>>notes.append ( 18 )
>>>print ( notes )
[10, 15, 8, 6, 18]
>>>notes[ 4 ] = 8
>>>print ( notes )
[10, 15, 8, 6, 8] 
>>>print ( [x+1 for x in notes] )

 


EXERCICE 2

Afficher les notes sur 10 en les divisant par deux.

Affecter une variable notesSur10 contenant les notes sur 10. Voici le début de la commande:

notesSur10 =

Faites la moyenne des notes sur 10 avec sachant qu’il y a une fonction sum() et une fonction len() sur une seule ligne.

On pourrait coder bien sûr comme ceci dans un fichier :

# Exercice 1

notesSur10 = [5.0, 7.5, 4.0, 3.0, 2.5]
somme = 0
nombreElement = 0

for x in notesSur10:
 somme = somme + x
 nombreElement = nombreElement + 1

print ( somme / nombreElement )

# Fin du programme

 

RÉPONSE A L’EXERCICE 2

Afficher la réponse pour avoir les notes sur 10 ->
>>> print( [ x /2 for x in notes ] )

Afficher la réponse pour avoir les notes sur 10 dans une variable notesSur10 ->
>>> notesSur10 = [ x /2 for x in notes ]

Créer une variable moyenne contenant la moyenne des notes sur 10 ->
>>> moyenne = sum ( notesSur10 ) / len ( notesSur10 )

 

 


Seconde partie de la formation >>>

 

 

 

Publié dans EuroMov DHM | Laisser un commentaire

Azure Spring deployment

This article is divided into two parts. First about Spring Boot Web Application and the second part is Tomcat Web Application without database.


Spring boot Web Application

1/ Create Web app with Azure account

Then choose to create a Web App of type Web App + Database :

Then provide information at first :

The « Ressource Group » is just a group of several « tools » provide by Azure in ours cases the already created empty group « sftp-test-europe » just provide networks settings, virtual network, database server, web app server and App Service plan.

We need to provide web app name here ceris1 as application name. This information will be used to create URL, database name, etc.

We provide the runtime stack of Java 17, and the Java web server stack  » Java SE (Embedded Web Server) ».

Then we choose MySql database and check « Hosting Basic for hobby or research » to avoid to paid too much for a test.

The second interface provides information to keep about MySQL settings include server host, login, password, and default database name ceris1-database for me. The default MySQL port should be 3306.

2/ Modification Spring application

Change the file applications.properties to provide the azure MySQL settings as :

I change the default Web server port from 8080 to 80 to create classical URL :

http://ceris1.azure.com/ 

We need to generate the final jar of our application, but we also need to avoid tests from Spring. Why, we do not have access to the Azure MySQL server to test our application, so the command will be :

mvn clean install spring-boot:repackage -DskipTests to create 

If the creation is OK, you will find a new jar file into :

C:\Dev23\Workspace-vscode-182.2\todo\target\todo-0.0.1-SNAPSHOT.jar

Then we need FTPS settings to upload the jar file, with « Deployement Center » we can find several methods but historical FTPS is simple :

We need FTPs server name (FTPS endpoint), FTP Username and Password to upload file.

Open Filezilla or any ftps client with settings, remove the default file into « /site/wwwroot » folder and drag and drop the newly created jar file :

You can test running the project with the Azure SSH console with :

The first time, open the consol is really slow, but I use it a lot to understand which settings is not OK about MySQL, port, java version, etc. That really useful.

Enter the command to start spring server with our development after may be a change directory to /home/site/wwwroot/ default folder :

java -jar todo-0.0.1-SNAPSHOT.jar

You should find the classical deployment information :

You should have a port 80 conflit at the end because the default web start application is still alive. Just « Restart » the web app from the Azure interface to let remove it after remove the default file with Filezilla or the Azure console.

Restart the application with the command line and test it online : https://ceris1.azurewebsites.net/.

NOTE: the automatic deployment from git server should be used be the purpose here is to understand the basic deployment from a simple jar application.


Tomcat War Web Application

From Eclipse Java EE, we suppose to have a Dynamic Web Project with servlet and JSP. At present, we will not include a database, but the process will be identical as Spring boot Web Application.

1/ Create Web App with Azure account

Then choose to create a Web App of type Web App :

Then provide information at first :

  • Resource Group : a group of applications of azure, but in our case it will a group of only this Web App
  • Name: Name of the instance just for URL, and to identify this Web App
  • Runtime stack: Java 17 for our web application
  • Java web start stack: Apache Tomcat 9.0
  • Pricing plan: free F1 (Shared infrastructure) to test this application for free

After the creation of the instance of web application (could take several minutes), we will consult the « deployment Center » and « FTPS credentials » that we will use to upload with FTP.

2/ Create and deploy war file

Open Eclipse Java JEE to create a war file from your application :

Right-click on your project, the menu Export > war file then provide the destination to create the file : c:/Dev24/app.war. You have to teep the app.war as the name of the war file.

Then use Filezilla to upload the file, but I find a bug from FTPS credential : use a FTP connection NOT FTPS to simply upload the file from C:\Dev24\ to the /site/wwwroot/ :

I delete the initial hostingstart.html welcome file installed by default by Azure Web App.

Then you can consult your application, which will deployed after a short delay (several minutes) :

The Web application will be slow because we only have a free container for purpose. We can consult the Azure ssh console into the browser to manage logs and information about tomcat.

Publié dans Développement, IMT Mines Alès | Laisser un commentaire

Formation python Seconde partie

 CINQUIÈME TRUC

Utilisation d’un  IDE (integrated development environment) performant pour gérer plusieurs fichiers pythons ou autre, plusieurs fichiers de données, plusieurs versions, etc.

Il y a de nombreux IDEs python, celui que je recommande actuellement est la version gratuite de PyCharm appelé PyCharm Community Edition (Si elle est après la version Pro plus bas dans la page) ; elle est très complète comme version.

A installer sur votre ordinateur comme habituellement, n’importez pas de « settings » et prenez les réglages par défaut.

Créez un nouveau projet, en fait un dossier qui va contenir vos futurs développements en python. Vous pouvez vérifier que PyCharm va bien utiliser python3.x pour vos développements.

Fermer le « Tip of the Day » et vous avez l’interface de PyCharm devant les yeux:

OK c’est ma version car vous n’avez en fait aucun dossier ni aucun fichiers actuellement. Donc par exemple, faites click droit dans la zone « Fichiers et dossier » dans le menu choisir:

New > Directory

Entrez le nom du dossier par exemple test et copier coller le fichier exercice1.py dedans.

Ouvrez le fichier exercice1.py en double cliquant dessus :

On peut exécuter le fichier exercice1 via le bouton en haut à droite ou le raccourci indiqué en survol de ce bouton. Le résultat de l’exécution sera visible donc dans la fenêtre du bas.


EXERCICE QUATRE

Télécharger le fichier de données à cette adresse : traitement_fichier.xls

Copiez le fichier dans PyCharm avec Copier / Coller et profiter pour renommer le fichier en traitement_fichier.txt :

Nous allons manipuler le fichier de données traitement_fichier.txt pour extraire de l’information, vous pouvez l’ouvrir dans PyCharm pour voir sa composition:

timestamp;latitude;longitude;altitude
1491486784141;43.64093363956815;3.851249759920415;109.30910031218662
1491486785141;43.64089947397977;3.8512505542990336;111.87747544303649
1491486786141;43.64088583922287;3.8512393755398326;113.0741231549388

...

Il s’agit des données en provenance d’un vol de planeur enregistré avec le GPS d’un smartphone.

On va donc dans le dossier test avoir le premier fichier exercice1.py, le fichier de données traitement_fichier.txt et on va ajouter un nouveau fichier, manipulation_fichier.py :

On va accéder au fichier pour afficher le contenu avec ces commandes:

with open("traitement_fichier.txt", "r") as fichier:
    contenu = fichier.readlines()
    print( contenu )
fichier.close()

Voici les données obtenus :

['timestamp;latitude;longitude;altitude\n', '1491486784141;43.64093363956815;3.851249759920415;109.30910031218662\n',

Nous devons en premier lieu traiter le problème du retour à la ligne « \n » en le retirant pour chaque ligne.

Voici le code pour traiter ligne à ligne la variable contenu en retirant à chaque fois le retour à la ligne:

with open("traitement_fichier.txt", "r") as fichier:
    contenu = fichier.readlines()
    for ligne in contenu:
        ligne = ligne.rstrip("\n")
        print(ligne)
fichier.close()

Vous pouvez voir que l’indentation du code en python remplace les end du Matlab. Ils ne sont donc pas optionnel, ils donnent un sens à ce qui est dans la boucle et ce qui n’est pas dans la boucle.

% Exemple Matlab valable mais non indenté
for c = 1:10
for r = 1:20
H(r,c) = 1/(r+c-1);
end
end

Nous allons ensuite nous concentrer sur le timestamp et l’altitude en extrayant que ces 2 colonnes:

with open("traitement_fichier.txt", "r") as fichier:
    contenu = fichier.readlines()
    for ligne in contenu:
        ligne = ligne.rstrip("\n")
        data = ligne.split(";")
        # ici afficher les colonnes 0 et 3 
fichier.close()

OK à vous , il faut extraire uniquement les altitudes qui ont été enregistré après le timestamp « 1491486791998 »

RÉPONSE A L’EXERCICE 4

Afficher la réponse pour avoir les altitudes ->


SIXIÈME TRUC

Test de quelques commandes dans l’interpréteur intégré de PyCharm. Nous avons avec PyCharme la possibilité de lancer des programmes dans l’IDE mais pour tester quelques lignes de commandes, l’IDLE est très pratique. Heureusement, nous pouvons avoir l’interpréteur de  commande dans PyCharm via le Menu Tools > Python Console …

Vous aurez ainsi la possibilité de tester quelques commandes avant de les intégrer dans votre fichier de commandes.


 EXERCICE CINQ

Afficher au format CSV les données suivantes pour les timestamps supérieurs à « 1491486791998 » avec un numéro de ligne incrémenté à chaque ligne:

1,1491486784141,109.30910031218662
2,1491486785141,111.87747544303649
3,1491486786141,113.0741231549388
4,1491486787141,112.96381095914386
5,1491486788142,113.037303562919
6,1491486789142,116.63811281139428
7,1491486790142,117.30185665137451

Nous allons donc créer une variable numero_ligne et l’incrémenté à chaque lecture de ligne :

numero_ligne = 0

Ensuite nous allons afficher les informations que nous voulons avec ce genre de ligne qui concatène les informations avec des « , »

print( numero_ligne + "," + data[0] + "," + data[3]  )

Mais malheureusement ou pas si vous essayez cette ligne que vous pouvez tester dans l’IDLE de Python ou en ouvrant l’interpréteur dans PyCharm comme vu précédemment.

numero_ligne = 0
print( numero_ligne + ","  )

Vous avez une erreur de type numero_ligne est de type entier (int en VO) et python ne veut pas prendre la responsabilité de le convertir en chaine de caractère (str en VO).

Essayez donc ceci encore une fois dans l’interpreteur:

unTexte = "1491486791998"
unNombre = int( unTexte )
unNouveauTexte = str( unNombre )

On doit donc convertir notre numero_ligne en str pour l’utiliser pour l’affichage.

En fait depuis le début on manipule des textes et non pas des nombres. Ce qui parfois va entrainer quelques problèmes de conversion que l’on verra plus tard.

RÉPONSE A L’EXERCICE 5

Afficher la réponse pour avoir les altitudes avec des numéro de lignes et un affichage en CSV ->


EXERCICE SIX

Maintenant, pour pouvoir enchainer les futurs traitements sur les données, le plus simple est de sauvegarder notre résultat au lieu de l’afficher à l’écran.

Pour écrire un fichier, on va faire en fin de notre programme comme ceci pour tester la création du fichier:

with open("extraction_fichier.txt", "w") as fichier_sortie:
    fichier_sortie.write( "numero_ligne;timestamp;altitude" )
fichier_sortie.close()

A vous d’intégrer ces modifications pour écrire non plus seulement une ligne d’entête mais toutes les données extraites précédemment dans ce fichier

RÉPONSE A L’EXERCICE 6

Ecrire les données extraites dans un fichier ->


SEPTIÈME TRUC

Le débugger est le meilleurs outil intégré dans les IDEs quelque soit le langage de programmation. Au lieu de ne disposer des erreurs ou des messages à la fin de l’exécution des programmes, le débuggeur fait exécuter étape par étape le programme.

La différence est similaire entre l’exécution d’une action de football en plein vitesse ou au ralenti:

Nous allons donc pour commencer ajouter un point d’arrêt à notre programme puis le faire exécuter ligne par ligne.

Pour bien débuter, nous allons mettre ce point d’arrêt à la première ligne de notre programme; plus tard nous mettrons ce point d’arrêt plus loin dans le programme car ce qui va nous intéresser sera non pas le début mais un endroit spécifique du programme.

C’est similaire avec l’action du but que l’on va décortiquer et non pas tout le début du match.

Placer le point d’arrêt en cliquant à droite du numéro de ligne, normalement un petit point rose indique que le point d’arrêt est actif.
Puis appuyer sur le bouton « Debug » en haut à droite juste à côté du bouton « Run ».

Le programme va démarrer et se mettre en pause sur la ligne avec le point d’arrêt. Pour enchainer ligne par ligne notre programme, nous allons utiliser soit le bouton « Ligne suivante » sur le dessin (Step over en VO) soit pour plus de simplicité la touche Fn+F8 sur MacOs et F6 sous Windows:

Nous pouvons avoir l’état des variables en mémoire soit dans la fenêtre du bas soit dans le code juste à droite de la ligne exécutée. Le mode debugage est très utile pour voir ce qui peut entrainer une erreur dans notre programme et en vérifiant l’enchainement qui est réalisé selon l’état des variables.

Pour retirer le point d’arrêt il faut cliquer de nouveau dessus. Vous pouvez avoir plusieurs points d’arrêt et les options de débogages sont très nombreuses, nous ne rentrerons pas dans les détails pour l’instant.


EXERCICE SEPT

Essaye le mode debugage sur votre programme pour vérifier l’enchainement des étapes.

Faites un point d’arrêt en face de l’instruction :

numero_ligne = numero_ligne + 1

Faites un clic droit sur le point d’arrêt et indiquer comme Condition:

numero_ligne == 10

Relancer le debugogage pour vérifier que le point d’arrêt ne se déclenche que quand cette valeur est atteinte.


EXERCICE HUIT

Nous voudrions obtenir le fichier de données suivant avec les timestamps qui sont transformé en intervalles de temps entre deux échantillonnages depuis un t zéro à la première valeur acquise par le GPS.

Ancien fichier:

timestamp;latitude;longitude;altitude
1491486784141;43.64093363956815;3.851249759920415;109.30910031218662
1491486785141;43.64089947397977;3.8512505542990336;111.87747544303649
1491486786141;43.64088583922287;3.8512393755398326;113.0741231549388
1491486787141;43.64090016392363;3.851241228679665;112.96381095914386

Nouveau fichier avec les intervalles de temps

1,0,109.30910031218662
2,1000,111.87747544303649
3,1000,113.0741231549388
4,1000,112.96381095914386
5,1001,113.037303562919
6,1000,116.63811281139428
7,1000,117.30185665137451
8,1857,117.30387542891553
9,1000,117.57712510977889
10,1000,118.1639542835122
11,1000,118.54163427393473

Calcul des intervalles de temps entre deux acquisitions ->


Troisième partie de la formation >>>

Publié dans EuroMov DHM | Laisser un commentaire

Formation python Troisème partie

 EXERCICE NEUF

Demander une information depuis la ligne de commande, pour filtrer les informations et ne garder que celle dont le numero_ligne est supérieur au numero_ligne_initial indiqué par l’utilisateur.

Pour demander une variable, voici la commande

numero_ligne_initial = input('Numéro de ligne initial: ')
numero_ligne_initial = int(numero_ligne_initial)

Normalement votre console va contenir ce message, avec le curseur pour attendre que vous indiquiez à partir de quel ligne on va traiter l’information

Numéro de ligne initial: _

 

Filtrer les informations à partir d’un numéro de ligne ->

 

 

 


HUITIEME TRUC

Les bibliothèques additionnelles sont très importantes dans python. Par défaut, python ne charge pas toutes les bibliothèques car cela prendrais trop de temps, cela chargerais en mémoire trop d’informations et même il y a risque d’incompatibilités entre certaines bibliothèques. Donc on charge que ce que l’on a besoin et on les importes individuellement.

Par exemple pour faire un graphisme, la bibliothèque que je propose est matplotlib.

Pour l’installer, il faut soit appeler en ligne de commande le logiciel pip par exemple via la commande du système d’exploitation (terminal sous MacOs, cmd sous Windows :

pip install requests

ou on trouve aussi la commande exprimée comme ceci:

python -m pip install <nom de la bibliothèque>

Ce que je conseille sinon c’est ce petit programme python qui exécute pip (qui est développé en python), à exécuté dans l’interpreteur python:

Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>import pip
>>>pip.main(['list'])
>>>pip.main(['install','<nom de la bibliothèque>'])

Mais ce qui est vraiment pratique avec PyCharm c’est que l’on peut faire via l’IDE tout cela:

Allez sur le Menu File > Settings…

NOTA: sous Mac Os le menu settings est déplacé dans le menu le plus à gauche portant le nom de l’application soit ici PyCharm > Settings…

Choisissez « Project: <votre projet> » puis « Project Interpreteur » et complètement à droite le bouton « + » puis vous pouvez chercher une bibliothèque (un package en VO) par exemple « matplotlib » pour l’installer.

Une fois l’installation terminé, on peut constater que matplotlib n’a pas été installé tout seul mais des bibliothèques additionnelles ont été aussi installé pour le faire fonctionner:

On peut constater que la bibliothèque numpy qui est très utile pour le calcul scientifique est aussi installé car elle est nécessaire à matplotlib.

 


NEUVIÈME TRUC

 

Pour l’utilisation de matplotlib et numpy pour faire une figure et des calculs, il faut en premier lieu importer les bibliothèques. Pourquoi indiquer dans un programme ce que l’on veut importer précisément, on pourrait penser que python va charger toutes les bibliothèques que l’on a installer, oui mais dans ce cas là on va avoir un long temps de chargement avant que notre programme ne s’exécute.

Pour importer l’objet qui gère dans la bibliothèque matplotlib l’objet qui gère les diagrammes, on peut écrire ceci:

from matplotlib import pyplot

Mais on trouve la version plus abrégé suivante:

import matplotlib.pyplot

Sauf qu’après on se retrouve à devoir faire préfixer toutes les fonctions de cet objet, par exemple ici la fonction figure() par le nom de la bibliothèque + le nom de l’objet:

matplotlib.pyplot.figure()

Donc on peut faire un alias (le mot après as) pour remplacer le préfixe par quelquechose de plus court

import matplotlib.pyplot as plt

et du coup l’appel se fait avec la version écourtée:

plt.figure()

Par exemple pour numpy la bibliothèque de calcul scientifique, son alias est souvent np.

 

Mais revenons à ce que nous avons besoin d’importer pour faire une courbe :

import matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D as ax3

Voici un petit morceau de programme pour tracer une courbe simple:

donnees = [18,22,4,15,15]
fig = plt.figure()
ax = fig.gca()
ax.plot( donnees , label='parametric curve')
plt.show()

Essayer d’afficher à l’écran cette courbe et modifier les données pour construire un autre exemple.

On peut faire une courbe avec deux dimensions :

donneesX = [1,2,3,15,18]
donneesY = [18,22,4,15,15]
fig = plt.figure()
ax = fig.gca()
ax.plot( donneesX, donneesY , label='parametric curve')
plt.show()

 


 EXERCICE DIX

Cette courbe est le début du vol du planeur enregistré par le GPS d’un smartphone.

Essayons de construire un programme pour l’afficher avec les données du fichier traitement_fichier.txt.

En premier lieu, importer matplotlib et numpy. Ensuite il faut créer trois tableaux pour stocker les informations:

#initialisation des tableaux de données
longitude = []
latitude = []
altitude = []

Puis après avoir passé la première ligne du fichier traitement_fichier.txt qui contient les entête des colonnes. Nous pouvons ajouter les valeurs lu comme str en valeur de type float (nombre à virgule) via ces lignes:

#construction des tableaux de données
latitude.append(float(data[1]))
longitude.append(float(data[2]))
altitude.append(float(data[3]))

Bien sur éviter de lire la colonne data[0] qui contient les timestamps peut utile pour ce diagramme.

A la fin de notre programme après avoir bien construit les 2 tableaux de données voici le code pour afficher le diagramme:

#dessin de la figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(longitude, latitude, altitude, label='parametric curve') 

# Ajouter des labels aux axes
ax.set_xlabel('longitude')
ax.set_ylabel('lattitude')
ax.set_ylabel('altitude')

plt.show()

 

A vous de jouer.

Affichage des données longitude, latitude, altitude ->

 

 


DIXIÈME TRUC

 

Si vous ne codez pas, tout cela ne va pas vraiment être utile.

Mettez des commentaires pour expliquer les morceaux du code.

Indiquez clairement ce que fait une variable, numero_ligne ou numeroLigne.

Faites des fichiers intermédiaires pour pouvoir rejouer l’intégralité ou une partie du processus.

Utilisez le débogage pour tracer l’enchainement du code et l’état des variables.

Installer pyinstaller avec la commande suivante :

pip install -U pyinstaller

Et vous pouvez ensuite créer un exécutable avec la commande suivante :

c:/Python311/Scripts/pyinstaller.exe --onefile ProjetPython\main.py -n projet.exe

L’exécutable se trouve alors dans le dossier dist/

 

Quatrième partie de la formation ⇒

 

 

Publié dans EuroMov DHM | Laisser un commentaire