Other tasks: 1, 2, 3, 4, 5, 6, 7.

General notes

Use your GitLab repository to submit your solutions. Please, use exact filenames as specified in the task name.

Please, respect language requirements of individual tasks. For Python, we expect Python 3 as the default (if you really need to use Python 2, use a proper shebang). For shell scripts, we expect that you will use Bash although none of the tasks requires any use of Bashisms for an efficient solution.

Deadline for this set of tasks is 2020-06-30 AoE, it is required to get at least 15 points from this group.

Tasks description

Team announcement (2 points)

Tasks in this group will be solved in teams of 2-3 students. The programming part will be relatively easy (see overall topic below), the focus will be on using tools for cooperation inside the team (such as issues in GitLab, branches in Git etc.).

Your first task is to form the team: find your team members and come up with a team name. Feel free to use mailing-list to find your team mates (it probably makes sense to include your preferred language (Bash or Python) in the invitation e-mail).

Once you finish this, we will create team repositories for you with the proper access.

To announce your team to us, follow this procedure (it ensures that team members are aware of their membership and we can easily check which teams are ready and you learn about Linux ACL).

  1. Create directory with team name on unixadmin.ms.mff.cuni.cz machine in /srv/nswi177/teams directory. The team name must conform to the following regular expression to be accepted: ^[a-zA-Z][a-zA-Z0-9_]{4,31}$ (i.e. normal identifier, English alphabet only)
  2. Set ACL rights on the directory so that only team members can create files inside this directory. man setfacl is probably the best source of information. However, these threads about disallowing access to everyone and allowing specific user access to a directory are perhaps more straightforward way how to complete this step.
  3. Each team member (including the one who run chmod and setfacl in previous step) must create empty file inside that directory with their login as the filename.
  4. Any of the team members must create file READY in the team directory to tell us that the team is ready once the team (i.e. all team members) complete step 3.

As an example, if users alice, bob and charlie wanted to create a team named we_are_the_best, we should see something like the following when running ls -l /srv/nswi177/teams/we_are_the_best:

-rw-rw-r-- 1 alice   alice   0 Apr 15 20:00 alice
-rw-rw-r-- 1 bob     bob     0 Apr 15 20:01 bob
-rw-rw-r-- 1 charlie charlie 0 Apr 15 20:02 charlie
-rw-rw-r-- 1 alice   alice   0 Apr 15 20:05 READY

and getfacl /srv/nswi177/teams/we_are_the_best would show something like this:

# file: .
# owner: alice
# group: alice
user::rwx
user:bob:rwx
user:charlie:rwx
group::rwx
mask::rwx
other::---

Topic (8 points)

Your program will work as a command-line client for openweathermap.org.

You can choose whether to implement the program in Python or in Bash. Both will have similar complexity and both languages have their strenghts that can be utilized when solving this task.

Submit your solution to your team repository. Do not use the solution-LOGIN repository but the team-TEAM one.

Your script should allow the user to keep a list of bookmarked locations and display current weather and forecast.

We expect an advanced user as to simplify the code a bit.

Before use, we expect that the user will retrieve his API key and register it with your application. UPDATE: we expect that the user will create the account at openweathermap.org and create the API key there. This API key is then passed to your application (i.e. do not retrieve the key from openweathermap.org by yourself or do not register a new user yourself). In other words, user needs to copy the key from this page.

User then can search for available locations; the search will show the location id to be used for other commands.

User can add locations to the bookmark list or remove existing ones.

Once the bookmark list is setup, running the application without extra parameters will display current weather and 2 day forecast for each bookmarked location.

We expect you will use the free API only, i.e. use the 5 day / 3 hour forecast data and pick some reasonable time of day to display the forecast (e.g. 12pm).

When the script is invoked with invalid parameters we expect you will print a reasonable error message and exit with non-zero exit code.

Example session could look like this:

$ my_owm register abcdef-and-the-rest-of-api-key
$ my_owm search prague
3067696 CZ Prague
4548393 US Prague
5039133 US New Prague
5093016 US Spragueville
6154028 CA Sprague
$ my_owm add 3067696
$ my_owm search brno
3078610 CZ Brno
$ my_owm add 3078610
$ my_owm list
3067696: Prague (CZ)
3078610: Brno (CZ)
$ my_owm
Prague: broken clouds, 17°C
 2020-04-25: broken clouds, 12°C
 2020-04-26: scattered clouds, 17°C

Brno: overcast clouds, 16°C
 2020-04-25: few clouds, 13°C
 2020-04-26: scattered clouds, 16°C
$ my_owm rm 3078610
$ my_owm
Prague: broken clouds, 17°C
 2020-04-25: broken clouds, 12°C
 2020-04-26: scattered clouds, 17°C

We expect that your script will support register, search, add, rm, list subcommands (plus no subcommand) and provide output as above (more or less).

Do not forget to (at least briefly) document your program.

Some (hopefully useful) hints

Look into owm_bits directory inside teaching/nswi177/2020-summer/upstream/examples.

There are examples for both Python and Bash that might help you jump-start your implementation.

logger demonstrates how to insert logging into your script with very little effort.

caching shows a simple implementation of file-based caching of downloaded files. It can be used for caching API requests too. It is not completely safe from concurrent issues but it is a good starting point. Note that it also shows you where to get list of all cities for fast searches in your application.

jq shows how to use the jq utility for querying infomation inside JSON data. Note that jq can be used for simple queries as well as quite complex ones.

get_current serves as a basic example on how to retrieve information from openweathermap.org. Note that you will need to paste your API key into owm.key file.

Finally, testing shows how one can easily inject artificial responses into your code to simplify testing (otherwise, it is really easy to hit the rate limit).

Detailed help for the API is also useful source of information:

Do not hesitate to use the mailing list if you have problems understanding the API (e.g. even for English-related issues).

UPDATES

Please, do not use any library such as pyowm that would simplify the your solution too much. We want you to implement the JSON response processing by yourself (however, use librarires for parsing JSON or making HTTP requests).

Please, place a install_my_owm.sh script into the root of your team repository. This script would install your implementation. For Python, we expect that it would use your ./setup.py to install your implementation. For Bash, install (copy) your script to $INSTALL_PREFIX/bin/my_owm (i.e. we will set the variable INSTALL_PREFIX for you before calling this script, probably to /usr/local/).

The purpose of this installer wrapper is to simplify automated testing. We expect that after this script is executed, we will be able to call my_owm from any location as it will be added to some directory on $PATH.

We expect that after calling register, the user can run other programs, change directory or even log-out and the registration will remain valid. I.e. we highly recommend storing the key in a plain text file (~/.config/owm-$TEAM/key or /~.owm-${TEAM}rc are good places).

Use of GitLab Issues (5 points)

The following will be graded for each team member separately.

UPDATE: Each team member must create at least three issues and close at least two issues. At least one of the issues has to be closed via a special commit message.

Hint: is is perfectly okay to create issues for to-be-done items.

Use of GitLab merge requests (5 points)

The following will be graded for each team member separately.

Each team member has to create at least three merge requests. Do not fork your repository, use branches inside the project to create the merge requests (we do not prohibit the fork but in such small team, it is probably not needed).

Each team member must merge at least two merge requests of other members of the team. We encourage that you discuss code quality etc. inside the merge request to keep things together.

Use a systematic naming for branches, consider tips from the labs.

Hint: merge requests are often used to close issues.

Continuous integration (5 points)

As a team, setup a continuous integration for your project (using GitLab runners).

We expect that you will run ShellCheck or PyLint and at least one other job too. Note that some subcommands actually do not require an API key and are thus good candidates for automated testing.

Also note that you can always inject artificial responses (see our examples) to provide reasonable tests. And trust us – having good tests will save you time in the long run.

Ostatní úlohy: 1, 2, 3, 4, 5, 6, 7.

Obecné požadavky

Úkoly odevzdávejte do Vašeho GitLabového repozitáře. Prosím, dodržujte přesné pojmenování souborů jak je uvedeno u názvu úkolu.

Prosím, dodržujte požadovaný jazyk jednotlivých úloh. Pro úlohy v Pythonu očekáváme použití Pythonu verze 3 (pokud doopravdy potřebujete verzi 2, nezapomeňte na správný shebang). Pro shellové skripty, očekáváme, že budete používat Bash. Nicméně, žádný z úkolů nevyžaduje použití Bashismu pro efektivní řešení.

Deadline pro tuto sadu úloh je 2020-06-30 KnZ, pro úspěšné splnění potřebujete získat alespoň 15 bodů.

Úlohy

Nahlášení týmu (2 body)

Úlohy v této skupině budou řešeny v týmech 2-3 studentů. Programovací část bude poměrně jednoduchá (téma je popsáno níže), úlohy se budou zaměřovat na používání nástrojů pro spolupráci v rámci týmu (např. větve v Gitu, issues v GitLabu atd.).

Váš první úkol je vytvořit tým: najděte si spolupracovníky a vymyslete jméno pro váš tým. Nebojte se využít mailing-list pro nalezení členů týmu (dává smysl rovnou připsat upřednostňovaný jazyk (Bash nebo Python) v prvotním e-mailu).

Jakmile toto budete mít hotovo, vytvoříme vám repozitář pro týmovou práci s přístupem pro všechny členy týmu.

Abyste nám sdělili složení a jméno vašeho týmu, použijte následující postup (který zaručí, že členové týmu jsou si vědomi svého členství, my můžeme jednoduše zjistit, které týmy jsou připravené a navíc se naučíte o Linuxových ACL).

  1. Vytvořte adresář s názvem týmu na stroji unixadmin.ms.mff.cuni.cz v adresáři /srv/nswi177/teams. Název týmu musí odpovídat následujícímu regulárnímu výrazu: ^[a-zA-Z][a-zA-Z0-9_]{4,31}$ (čili obvyklý identifikátor, bez nabodeníček apod.).
  2. Nastavte ACL oprávnění na adresáři tak, aby pouze členové týmu mohli vytvářet soubory uvnitř tohoto adresáře. man setfacl je asi nejlepší zdroj informací. Nicméně, následující vlákna o znepřístupnění všem a povolení přístupu konkrétním uživatelům jsou možná přímočařejším řešením tohoto kroku.
  3. Každý člen tému (včetně toho, který spustil chmod a setfacl v předchozím kroku) musí vytvořit prázdný soubor v týmovém adresáři pojmenovaný podle svého přihlašovacího jména (loginu).
  4. Libovolný z členům týmu pak musí vytvořit soubor READY, kterým nám oznámí, že tým je kompletní (tj. všichni členové dokončili krok č. 3).

Pokud by uživatelé alice, bob a charlie chtěli vytvořit tým we_are_the_best, viděli bychom pro výstup příkazu ls -l /srv/nswi177/teams/we_are_the_best něco podobného:

-rw-rw-r-- 1 alice   alice   0 Apr 15 20:00 alice
-rw-rw-r-- 1 bob     bob     0 Apr 15 20:01 bob
-rw-rw-r-- 1 charlie charlie 0 Apr 15 20:02 charlie
-rw-rw-r-- 1 alice   alice   0 Apr 15 20:05 READY

a getfacl /srv/nswi177/teams/we_are_the_best by vypsalo něco jako:

# file: .
# owner: alice
# group: alice
user::rwx
user:bob:rwx
user:charlie:rwx
group::rwx
mask::rwx
other::---

Téma (8 bodů)

Váš program bude fungovat jako klient příkazové řádky pro openweathermap.org.

Můžete si vybrat, zda-li chcete programovat v Pythonu nebo v Bashi. V obou případech bude složitost programu podobná, oba jazyky mají své přednosti, které můžete využít při řešení této úlohy.

Řešení odevzdejte do týmového repozitáře. Nevkládejte řešení do repozitáře solution-LOGIN ale do team-TEAM.

Váš skript musí uživateli umožnit udržovat si seznam uložených míst (oblíbené) a zobrazit aktuální počasí a předpověď pro tato místa.

Počítáme s pokročilými uživateli, což by mělo trochu usnadnit implementaci.

Před zahájením práce očekáváme, že uživatel si zjistí svůj API klíč a zaregistruje ho ve vaší aplikaci. AKTUALIZACE: očekáváme, že uživatel si vytvoří sám svůj účet na openweathermap.org a vytvoří si tam API klíč. Tento API klíč poté předá vaší aplikaci (tj. nevyzvedávejte si klíč z openweathermap.org přímo sami ani neregistrujte nového uživatele). Jinými slovy, uživatel zkopíruje svůj klíč z této stránky.

Uživatel pak může hledat v dostupných místech; hledání zobrazí i interní ID, které se budou používat v dalších příkazech.

Uživatel může přidávat a odebírat místa ze seznamu uložených míst.

Jakmile jsou oblíbená místa připravená, spuštění aplikace bez dalších parametrů zobrazí aktuální počasí a předpověď na 2 dny (pro každé z uložených míst).

Očekáváme, že budete používat pouze API zdarma, tj. použijte 5 day / 3 hour forecast data a vyberte si nějaký rozumný čas pro zobrazení předpovědi (např. poledne).

Pokud bude skript spuštěn s neplatnými parametry, očekáváme, že vytiskne rozumnou chybovou hlášku a skončí s nenulovým návratovým kódem.

Ukázková práce s program může vypadat třeba takhle:

$ my_owm register abcdef-a-zbytek-api-klice
$ my_owm search prague
3067696 CZ Prague
4548393 US Prague
5039133 US New Prague
5093016 US Spragueville
6154028 CA Sprague
$ my_owm add 3067696
$ my_owm search brno
3078610 CZ Brno
$ my_owm add 3078610
$ my_owm list
3067696: Prague (CZ)
3078610: Brno (CZ)
$ my_owm
Prague: broken clouds, 17°C
 2020-04-25: broken clouds, 12°C
 2020-04-26: scattered clouds, 17°C

Brno: overcast clouds, 16°C
 2020-04-25: few clouds, 13°C
 2020-04-26: scattered clouds, 16°C
$ my_owm rm 3078610
$ my_owm
Prague: broken clouds, 17°C
 2020-04-25: broken clouds, 12°C
 2020-04-26: scattered clouds, 17°C

Očekáváme, že váš skript bude podporovat podpříkazy register, search, add, rm a list (plus spuštění bez podpříkazu) s výstupem jako je uvedený výše (více méně).

Nezapomeňte na (alespoň stručnou) dokumentaci Vašeho programu.

Několik (snad užitečných) tipů

Podívejte se do adresáře owm_bits v teaching/nswi177/2020-summer/upstream/examples.

Jsou tam příklady pro Python i Bash, které by vám mohli pomoci nastartovat práci na vaší implementaci.

logger demonstruje, jak lze jednoduše přidat logování do vašeho programu.

caching je jednoduchá implementace cachování (založeného na souborech). Může být též použita pro cacheování API požadavků. Není úplně bezpečná při vícenásobném souběžném přítupu, ale pro začátek by mohla stačit. Mimo jiné také ukazuje, kde lze získat seznam všech měst pro zrychlení vyhledávání ve vaší aplikaci.

jq ukazuje použití prográmku jq pro zjištění informací z JSON dat. Všimněte si, že jq zvládá jak pro jednoduché dotazy, tak i poměrně komplikované.

get_current slouží jako příklad práce s API nad openweathermap.org. Pro správnou funkci musíte vložit váš API klíč do souboru owm.key.

A konečně, testing ukazuje, jak lze jednoduše pracovat s testovacími odpověďmi (rate limiting je jinak poměrně přísný).

Je také dobré vědět o nápovědě k API:

Nebojte se konzultovat problémy přes mailing-list (i např. kvůli problémům při chápání anglické dokumentace API).

AKTUALIZACE

Prosím, nepoužívejte žádnou podobnou knihovnu jako např. pyowm, která by úlohu příliš zjednodušila. Chceme, abyste vy implementovali zpracování JSONové odpovědi (ale určitě použijte knihovny pro parsování JSONu a posílání HTTP požadavků).

Prosíme, do kořenového adresáře vašeho týmového repozitáře umístěte skript install_my_owm.sh, který nainstaluje vaše řešení. Očekáváme, že pro Python využije váš ./setup.py k instalaci vašeho programu. Pro Bash, nainstalujte (nakopírujte) váš skript do $INSTALL_PREFIX/bin/my_owm (tj. my nastavíme proměnnou INSTALL_PREFIX před tím, než zavoláme tento skript, pravděpodobně bude mířit na /usr/local/).

Důvodem pro tento instalační wrapper je zjednodušení automatického testování. Očekáváme, že po jeho doběhnutí budeme moci zavolat my_owm z libovolného adresáře, protože bude v nějakém adresáři, který je v $PATH.

Očekáváme, že po volání register bude uživatel moci spustit jiné programy, změnit pracovní adresář nebo se odhlásit ze systému a registrace zůstane platná. Tj. velmi doporučujeme uložit klíč do obyčejného textového souboru (~/.config/owm-$TEAM/key nebo /~.owm-${TEAM}rc jsou rozumná umístění).

Používání GitLab Issues (5 bodů)

Následující bude hodnoceno pro každého člena týmu zvlášť.

AKTUALIZACE: Každý člen týmu musí vytvořit alespoň tři issues a uzavřít alespoň dvě issues. Alespoň jedna issue musí být zavřena pomocí speciálního textu v commitu.

Tip: je naprosto v pořádku mít issue pro nedokončené položky.

Používání merge requestů v GitLabu (5 bodů)

Následující bude hodnoceno pro každého člena týmu zvlášť.

Každý člen týmu musí vytvořit alespoň tři merge requesty. Neforkujte váš repozitář, použijte větve uvnitř projektu pro vytváření merge requestů (forkování nezakazujeme, ale pro malý tým jsou větve uvnitř projektu naprosto dostačující).

Každý člen týmu musí přimergovat alespoň dva merge requesty jiného člena týmu. Doporučujeme, abyste merge requesty využili k diskuzi nad kódem apod. a měli tak informace hezky pohromadě.

Větve pojmenovávejte systematicky zvažte nápady ze cvičení.

Tip: merge requesty často slouží k uzavření issues.

Continuous integration (5 bodů)

Jako tým, nastavte continuous integration pro Váš projekt (pomocí GitLab runnerů).

Očekáváme, že budete pouštět ShellCheck nebo PyLint a alespoň jednu další úlohu. Některé podpříkazy nevyžadují API klíč a jsou tudíž dobrými kandidáty na automatické testování.

Také připomínáme, že můžete vždycky vložit testovací data do libovolného podpříkazu pro snazší otestování (vizte naše příklady). A věřte nám – dobré testy vám nakonec čas vždy ušetří.