Chapter 15: Pomoc dla web2py
Pomoc dla web2py: błędy, ulepszenia i dokumentacja
Projekt web2py jest bardzo przyjazny pod względem zgłaszania błędów, ulepszania dokumentacji i poprawek.
Grupa Google
Główne forum dla omawiania błędów i nowych funkcjonalności, to: web2py-users (Adres URL to https://groups.google.com/forum/#!forum/web2py
)
Zgłaszanie błędów
Do stycznia 2015, sprawy (ang. issues) były śledzone na Google Code i wiele historycznych odniesień w grupie dyskusyjnej i w starej dokumentacji będzie dalej tu dostępnych. W ramach migracji do GitHub, projekt wykorzystuje teraz mechanizm śledzenia spraw GitHub. Do GitHub zostały przetransferowane tylko otwarte sprawy.
Jeśli znalazłeś/znalazłaś błąd i chcesz go omówić na grupie dyskusyjnej, możesz zostać poproszony o zgłoszenie błędu (ang. bug report) przez utworzenie sprawy na Issue w GitHub.
Proszę odwiedzić stronę projektu na GitHub i uruchomić odnośnik do Issues, lub bezpośrednio odwiedzić strone https://github.com/web2py/web2py/issues.
Jak zwykle, dobre zgłaszanie błędów oznacza, że musimy znać, jakiego używasz systemu operacyjnego, jaką wersję Pythona i web2py, czego oczekiwałeś/oczekiwałaś a co się stało.
Zgłaszanie błędów bezpieczeństwa
Podczas zgłaszania błędów bezpieczeństwa trzeba zachować ostrożność, aby nie ujawnić informacji, które mogłyby się przyczynić do szkodliwego wykorzystania kodu. Po wysłaniu informacji na grupę Google lub utworzeniu sprawy na GitHub, skontaktujemy się z Tobą przez programistę w celu prywatnej wymiany informacji.
Współtworzenie kodu i zmiany w dokumentacji
Jak zarządzany jest projekt?
Podstawowy kod web2py jest zarządzny w repozytorium git na GitHub. Oryginalnym systemem kontroli wersji był Mercurial na Google Code, ale obecnie projekt tworzony jest na GitHub.
PyDAL: DAL jest teraz niezależnym projektem
Ważną częścią web2py jest Database Abstraction Layer (DAL). Na początku 2015 roku została ona wyłączona do projektu (PyDAL). W nomenklaturze Git jest to podmoduł głównego repozytorium.
Wykorzystanie podmodułu wymaga jednorazowego uzycia flagi --recursive
dla git clone
jeśli klonuje się web2py od podstaw.
Jeśli ma się już istniejące repozytorium, ponizsze polecenie musi być wykonane tylko raz:
git submodule init
git submodule update
rm -r gluon/dal
PyDAL używa odzielnego cyklu wydawania wersji stabilnej, niezależnie od reszty web2py. Wydania PyDAL używają schematu nazewnictwa opartego na datach, podobnego do Ubuntu. Sprawy dotyczące PyDAL powinny być zgłaszane do jego repozytorium.
Repozytoria GitHub
Repozytoriami GitHub są:
https://github.com/web2py/web2py https://github.com/web2py/pydal
Platforma web2py ma dwie ważne wersje: bieżącą stabilną i migawkę rozwojową. Migawka rozwojowa jest przeważnie określana w Git mianem gałęzi "master", która jest odpowiednikiem gałezi "trunk" w Mercurial.
Poprawki błędów i ulepszenia kodu zgłaszane są do gałęzi "master". Najlepiej zrobić to poprzez sklonowanie repozytorium Git. Jest to pierwszy krok do używania kodu przechowywanego na GitHub i jest tam dobrze to udokumentowane. Ponieważ wydania są tagowane, więc można przełaczać się pomiedzy gałęzią "master" a określonym wydaniem. To czyni repozytorium bardzo praktycznym, nawet w produkcji.
Do tego są potrzebne podstawowe umiejętności z zakresu obsługi repozytoriów Git:
- klonowanie repozytorium hostowanego na GitHub;
- przełaczanie się pomiędzy gałęziami;
- przełaczanie gałęzi opartej na tagach.
Jest to wszystko bardzo dobrze omówione w poradnikach na GitHub.
Omawianie propozycji zmian
Jeżeli zmiana dotyczy błędu, dyskusja będzie się przypuszczalnie toczyć na "Issue" na GitHub (patrz wyżej). Jeżeli zmiana ma charakter polepszenia istniejącego kodu lub dodania nowych funkcjonalności, to najlepszym miejscem jest w tym przypadku forum grupy programistów: grupa web2py-developers.
Ponieważ web2py przyrzekło kompatybilność wsteczna dla funkcjonalnosci nieeksperymentalnych, akceptowanie zmian w podstawowym kodzie wiąże się z koniecznoscią utrzymania tej kompatybilności w przyszłości - obietnicy nie można lekceważyć.
Mniej doświadczeni użytkownicy mogą z dyskusji dowiedzieć się, że już istnieje metoda na osiagniecie tego, co chcą. Niestety dokumentacja jest czasem opóżniona w stosunku do juz dokonanych zmian w kodzie (zobacz niżej, jak ulepszać dokumentację), stąd forum może okazać się cennym źrodłem wiedzy.
Gdy bedzie się już gotowym do zgłoszenia zmian kodu, dyskusja zostanie przypuszczalnie przeniesiona do komentarzy załączonych do żądań aktualizacji (ang. Pull Request), co jest oówione poniżej.
Styl kodowania
Ogólnie rzecz biorąc, nalezy przestrzegać stylu kodowania PEP8: http://www.python.org/dev/peps/pep-0008/
Tutaj mozna znaleźć konkretne wytyczne: styl kodowania web2py
Styl dokumentowania
Styl dokumentowania jest określony poniżej.
Porady na temat konfigurowania środowiska programistycznego
W rozdziale 13 oówione jest wykorzystywanie platform IDE w web2py.
Przygotowanie: przy użyciu GitHub
Ponieważ web2py używa GitHub, ogólny przepływ zmian jest następujący:
- Utwórz klon projektu web2py na GitHub, co w nomenklaturze GitHub nazywa się rozwidleniem (ang. forking).
- Na komputerze lokalnym utwórz klon swojego rozwidlenia web2py i dokonaj tam zmian.
- Utwórz nową gałąź dla swoich zmian.
- Pracuj w utworzonej gałęzi i wprowadź zmiamy (
commit
). - Wypchnij te zmiany do swojego rozwidelenia projektu na GitHub (
git push orgin name_of_new_branch
). - Wykonaj na GitHub żądanie aktualizacji (ang. pull request).
- Jeżeli to żądanie aktualizacji zostanie zaakceptowane. Twoja rewizja pojawi się w kodzie gałęzi 'master' projektu web2py.
W chwili pisania tego artykułu, podstawowe techniki git/GitHub są opisane na: https://help.GitHub.com/articles/fork-a-repo
W przypadku "łat" trzeba jednak postępować zgodnie z niżej opisaną instrukcją.
Proszę pamiętać: repozytorium Git web2py zawiera podmoduł dla DAL. Oznacza to, że w poleceniu klonujacym projekt powinno się użyć parametr --recursive
, aby pobrać tez kod podmodułu.
Przygotowanie: wykorzystywanie Travis-CI z rozgałęzieniem z GitHub
Platforma web2py działa także z Travis-CI, usługą testowania z ciagła integracja. Oznacza to, że każde zatwierdzenia zmian wyzwala zintegrowane testy jednostkowe.
Łatwo mozna dodawać Travis do swojego repozytorium, aby uniknąć przesyłania łat, które mogą spowodować niepowodzenie testów Travisa.
prosze postępować zgodnie z instrukcja na stronie: http://about.travis-ci.org/docs/user/getting-started/
Cztery elementy składajace się na dobra jakość poprawek
Poprawki wysokiej jakości powinny cechowac się:
- Zmiana kodu;
- Udokumentowaniem zmian w API (zobacz poniżej dokumentowanie API);
- Przetestowaniem nowych funkcjonalności;
- Zaktualizowaniem podręcznika (który jest również utrzymywany na GitHub).
Uzyskanie czystej poprawki: korzystanie z prawidłowej techniki gałęziowej Git
Właściwe korzystanie z Git jest nieco trudniejsze w projektach współdzielonych.
Oto wytyczne, których przestrzeganie powinno zapewnić, ze żądanie aktualizacji (ang. pull request) powinno być zastosowane czysto (bez konfliktów).
Po pierwsze upewnij się, masz ustawone zewnętrzne repozytorium tak, że wskazuje to na główne repozytorium web2py na GitHub. To zewnętrzne rpozytorium powinno mieć nazwę upstream. Wystarczy to ustawić tylko raz.
Dodawanie repozytorium upstream jest omówione we wstępnym artykule GitHub, który został przytoczony powyżej. Dodaj zdalne repozytorium do swojego lokalnego repozytorium:
git remote add upstream https://GitHub.com/web2py/web2py/
Następnie ustaw nazwę gałęzi dla swoich zmian. W Git można stosować w miarę opisowe nazwy gałęzi. Dla web2py polecamy takie nazwy jak:
- każda rewizja z poprawką błędu powinna pochodzić z gałęzi o nazwie "issue/numer_sprawy_na_github" (na przyklad issue/1684);
- każda rewizja ulepszajca powinna pochodzić z gałęzi o nazwie "enhancement/tytuł_poprawki" (na przykład enhancement/trapped_links)
W lokalnym repozytorium zmień gałąź (w poniższym kodzie zmień CHANGE1
na nazwę swojej gałęzi:
git fetch upstream
git checkout -b CHANGE1 upstream/master
... Wykonaj zmiany lub przełacz się do innej lokalnej gałązi. Wykonaj rewizję (ang. commit) jeśli jest to niezbędne. Gdy już będzie wszystko gotowe, prześlij zmiany do swojego rozgałęzienia web2py na GitHub:
git push origin CHANGE1
i teraz przejdź na swoją stronę na GitHub, przełącz się tam do nowej gałęzi i wykonaj żądanie aktualizacji (ang. pull request), zwane też w skróce "PR". GitHub wyświetla przycisk "delete branch" po tym jak PR zostało zespolone (ang. merge) lub zmknięte. Nie ma żadnych gwarancji, ale żądania aktualizacji są przegladane co kilka dni. Większość osób składa poprawki jako żądania aktualizacji również aktualizując inne wątki poruszone w systemie śledzenia spraw.
Dodawanie testów
Gdy dodawane są poprawki zmieniające lub dodające funkcjonalność trzeba wykonać testy jednostkowe. Testy są skryptami Pythona zawartymi w katalogu gluon/tests. Przyjrzyjmy się podejściu stosowanemu w testach. Można zauważyć, że testy często potrzebują utworzenia tabeli, wykonania testu danej funkcjonalności i sprawdzenia danych wyjsciowych oraz powrócenie do stanu z przed testu (co w tym przypadku oznaczałoby usunięcie tabeli. Proszę zapoznać się z artykułem Web2pyslice 1691.
Uruchomienie testów
Testy uruchamia się poleceniem:
python web2py.py --run_system_tests
Proszę zapoznać się z wyżej cytowanym artykułem na witrynie 'slice', który zawiera wiecej informacji na ten temat, w tym o indywidualnym uruchamianiu testów.
Przykład testu jednostkowego
Pisanie testów jest łatwe. To jest przykład zaczerpnięty z gluon/tests/test_dal.py. Można tu zobaczyć jak rozszerzana jest klasa TestCase, jak dodawana jest wystarczajaco złożona tabela danych, jak wykonywany jest test i jak sprawdzane są dane wyjściowe oraz jak następnie usuwane są dane z bazy danych wraz z tabelą, pozostawiając miejsce testu tak czystym jak przed jeso wykonaniem.
class TestVirtualFields(unittest.TestCase):
def testRun(self):
db = DAL(DEFAULT_URI, check_reserved=['all'])
db.define_table('tt', Field('aa'))
db.commit()
db.tt.insert(aa="test")
class Compute:
def a_upper(row): return row.tt.aa.upper()
db.tt.virtualfields.append(Compute())
assert db(db.tt.id>0).select().first().a_upper == 'TEST'
db.tt.drop()
db.commit()
Dokumentacja: aktualizowanie podręcznika
Podręcznik jest również utrzymywany na GitHub i w tym przypadku można stosować ten sam schemat pracy, jak poprzednio. Źródło podręcznika zawiera kilka wersji językowych, w katalogu "sources". Zawartość jest napisana w markmin . Podręcznik jet aplikacją web2py app. Najlepiej jest wykonać rozgałęzienie (ang. fork) projektu książki i sklonować go do lokalnego repozytorium w katalogu "applications" instalacji web2py. To umożliwia natychmiastowe zobaczenie w przegladarce internetowej wprowadzonych przez siebie zmian jak też utrzymanie podręcznika w stanie najbardziej aktualnym (porzez ściaganie zmian z repozytorium zdalnego).
W przypadku polskiego tłumaczenia, pełna instrukcja znajduje się na stronie wikipedii polskiego tłumaczenia tego podręcznika.
Dokumentacja: web2pyslices.com
Witryna web2pyslices.com jest źródłem dla recept, wstawek kodowych i przykładów.
Dokumentacja: API i dokumentacja w komentarzach kodu
Dokumentacja API web2py API jest utrzymywana na stronach readthedocs.org.
Wykorzystuje ona system dokumentacyjny Sphinx, co oznacza, że jest generowana automatycznie z plików źródłowych.
Dokumentacja API (czyli łańcuchy dokumentujace "docstrings") i dokumentacja komentarzowa powinny spełniać wymagania Google Python Style Guide - Comments.
Oto przykład zaczerpnięty z kodu web2py:
def getcfs(key, filename, filter=None):
"""
Caches the *filtered* file `filename` with `key` until the file is
modified.
Args:
key(str): the cache key
filename: the file to cache
filter: is the function used for filtering. Normally `filename` is a
.py file and `filter` is a function that bytecode compiles the file.
In this way the bytecode compiled file is cached. (Default = None)
This is used on Google App Engine since pyc files cannot be saved.
"""
a to przykład uwzględniający zasady stylów Google:
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
"""Fetches rows from a Bigtable.
Retrieves rows pertaining to the given keys from the Table instance
represented by big_table. Silly things may happen if
other_silly_variable is not None.
Args:
big_table: An open Bigtable Table instance.
keys: A sequence of strings representing the key of each table row
to fetch.
other_silly_variable: Another optional variable, that has a much
longer name than the other args, and which does nothing.
Returns:
A dict mapping keys to the corresponding table row data
fetched. Each row is represented as a tuple of strings. For
example:
{'Serak': ('Rigel VII', 'Preparer'),
'Zim': ('Irk', 'Invader'),
'Lrrr': ('Omicron Persei 8', 'Emperor')}
If a key from the keys argument is missing from the dictionary,
then that row was not found in the table.
Raises:
IOError: An error occurred accessing the bigtable.Table object.
"""
pass
Oto uwagi dotyczące dokumentacji API i komentarzy dokumentujacych:
- Funkcjonalności eksperymentalne powinny być jawnie oznaczone jako "experimental".
- Jako system dokumentacyjny wybrany został Sphinx, ze względu na jego możliwości, fakt że jest traktowany jako wiodący system dokumentacyjny dla projektów Pythona oraz ze względu na to, że ma dodakowy bonus w postaci serwisu readthedocs.org.
- Nowe funkcjonalności powinny być jawnie oznaczone (np. "starting from 2.4.6...").
- Nowe funkcjonalności powinno się odnieść ściśle do oficjalnego pliku "changelog".
- readthedocs.org pozwala budować "statycznie zlinkowane" wersje dokumentacji z tagami wydań (dobra rzecz do porównywania wersji)
- Programiści web2py mogą stosować styl Google, tak jak oferuje to najlepiej Sphinx, bez wszystkich klopotliwych "dekoracji" ReST.
- Do wersji Sphinx 1.3, do budowania dokumentacji wymagane jest rozszerzenie "napoleon.