gambas3 verdwenen na update openSUSE

Gambas3 is verdwenen …
– uit de repo’s van opensuse Tumbleweed
– uit het development menu na de zypper dup update van openSUSE Tumbleweed;
Gambas3-ide komt niet voor bij software, maar de andere onderdelen als de runtime zijn wel (nog) aanwezig, bv:

gambas3-runtime - Gambas runtime interpreter

Version:
3.19.3-1.2
Build Time:
Wed 03 Jul 2024 01:46:34 PM CEST
Install Time:
Fri 05 Jul 2024 05:25:44 PM CEST
License:
GPL-2.0-or-later
Installed Size:
2.2 MiB
Download Size:
0 B
Distribution:
home:munix9 / openSUSE_Tumbleweed
Vendor:
obs://build.opensuse.org/home:munix9
Packager:

Architecture:
x86_64
Build Host:
reproducible
URL:
https://gambas.sourceforge.net/
Source Package:
gambas3-3.19.3-1.2
Media No.:
0
Authors:

Andere versies/repo’s

In de education repository is gambas 3.14 aanwezig, dus die repo aanzetten zou een mogelijkheid kunnen zijn als een oudere versie volstaat.

In de home:Henry15ea Community is versie 3.18.1 aanwezig.

Andere openSUSE versies

In openSUSE 15.5 waren de updates gebeurd tot 2024-07-28
OpenSUSE 15.5: Gambas3 v 3.19.3
. Nu in Yast, Software Management staat alles van Gambas3 “rood”; ik heb de hele gambas3 lijst van programma’s “protected” gezet.

In openSUSE 15.4 in Yast staat alles van Gambas3, versie 3.18.4 “rood”.

Gambas3 is niet meer terug te vinden in de repo waar het uit geïnstalleerd is (obs:/:build.opensuse.org/home:munix) Zie ook software.opensuse.org

Over het verdwijnen uit de munix repo is nergens iets te vinden op dit moment.

Het heeft blijkbaar met openSUSE (of de – versie) te maken …

Op de website van gambas is niets abnormaals gemeld.

Vertrek van de bron
Mogelijkheid: de broncode van gambas afhalen en zelf compileren tot werkend programma.
Dat lukte op deze manier nog met versie 3.19.90 (20-8-2024).

Listbox_Click, Message.Question, Listbox.Remove

OpenSUSE-KDE-Plasma Gambas 3.19.3 qt5

Een eigenaardig feonomeen: ik laat de gebruiker op de listbox klikken, waarop gevraagd wordt of hij de betreffende listbox lijn (aangeduid door Listbox.index) wil verwijderen. Zo ja, verwijder ik die met Listbox.Remove(Listbox.Index).

Mijn voorbeeld: de listbox (Mode: Single) bevat 1 lijn. Ik klik op knop 1.

Code:

Public Sub lsbxError_Click()
  Dim i As Integer
'  
  i = Message.Question(lsbxError.Index & ": " & lsbxError.Text, "Clear", "Clear All", "Cancel")
  Debug i
  Select i 
    Case 1
      lsbxError.Remove(lsbxError.Index)
    Case 2
      lsbxError.Clear
    Case 3
    ' else do nothing
  End Select
'
End

Na het verwijderen van de lijn krijg ik een nieuwe vraag met een lege tekst en als index -1. Als je nog eens op Clear klikt, krijg je een foutmelding Out of bounds
.. op de lijn van de Remove; het gaat blijkbaar over de index.

Ik merk op (bij meer elementen) dat de listbox na het verwijderen een ander item selecteert (zonder dat ik dat expliciet vraag), dat ik dan ook niet meer kan kiezen voor verwijderen.
Ik kan de fout blijkbaar vermijden door een “unselect” toe te voegen:

Public Sub lsbxError_Click()
  Dim i As Integer
  '
  i = Message.Question(lsbxError.Index & ": " & lsbxError.Text, "Clear", "Clear All", "Cancel")
  Debug i
  Select i 
    Case 1
      lsbxError.Remove(lsbxError.Index)
      lsbxError.UnselectAll()
    Case 2
      lsbxError.Clear
    Case 3
    ' else do nothing
  End Select
'
End

en de “index” fout kan ik vermijden door op voorhand een voorwaarde toe te voegen:

Public Sub lsbxLog_Click()
  Dim i As Integer
  
  Debug lsbxLog.Index
  If lsbxLog.Index >= 0 Then
    i = Message.Question(lsbxLog.Text, "Clear", "Clear All", "Cancel")
    Select i
      Case 1
        lsbxLog.Remove(lsbxLog.Index)
        lsbxLog.UnselectAll()
      Case 2
        lsbxLog.Clear
      Case Else
        ' else do nothing
    End Select
  Endif
  
End

Raspbian 11: $EDITOR gezocht

Editor of $EDITOR?
Een van de eerste dingen die opvallen na installatie van Gambas3 op de Raspberry Pi met OS Raspbian GNU/Linux 11 is dat Gambas naar de “Editor” vraagt bij het openen van een bestaand (git-)project:

Please set the $EDITOR environment variable with your favorite graphical text editor. Some version control commands need it

Dit heb ik opgelost door de volgende lijn toe te voegen aan /etc/profile.
export EDITOR=/usr/bin/mcedit

Select-editor
De .bashrc oplossing zoals andere Linux distributies (bv OpenSUSE Gambas opstart set $Editor) werkt hier niet op Raspbian.
De Raspberry Pi heeft zijn eigen tool voor het instellen van de editor (waarvan het resultaat niet herkend werd door Gambas), het commando

select-editor.

Daarna krijg je een keuzemenu met genummerde mogelijkheden, en kan je met een cijfer je keuze maken, bv 1. Nano.
Als je zelf bv al midnight commander geïnstalleerd had, komt mcedit ook voor in de keuzelijst.
Select-editor toont helaas niet wat de huidige keuze is.
Na de keuze zet select-editor een verborgen bestand .selected_editor in je home direoctory, met daarin
SELECTED_EDITOR="/usr/bin/mcedit"
Ik vermoed dat het bij de volgende start/login gelezen wordt.

Of toch niet?
Maar Gambas blijft de $EDITOR variabele vragen, zelfs na de volgende login. 
Ik weet dat de keuze aktief is door een test met crontab -e.

Het bestand ~/.bashrc bestaat ook hier, en ik voeg toe: 
EXPORT EDITOR=/usr/bin/mcedit
maar op geen enkele manier (met aanhalingstekens, zonder, met $, zonder..) werkt dat.
(m.a.w. Gambas3 blijft de vraag stellen).

Ik probeer de volgende lijn  toe te voegen aan /etc/profile:
export EDITOR=/usr/bin/mcedit
(sudo nodig).

Na herstarten op de commandline 
echo $EDITOR
/usr/bin/mcedit

Deze keer ok!

Fout in Library

Door een fout in een library kreeg ik in mijn applicatie (het programma dat die library gebruikte) fouten die ik niet begreep.

Library:

ExampleObject
– id
– SomeExternalId
– otherdata

In de library zat ook een module om de gegevens te bewaren in- en op te vragen uit de database.

Testprocedures in mijn library konden perfect een ExampleObject maken in de de database bewaren.

Mijn eindprogramma niet.

Als in in mijn eindprogramma directe sql code schreef, ging het daar wel.

De fout zat in het ExampleObject in de loadFromDb code.

If resDb.Available
$lId = resDb!id
- $lExternalId = resDb!Xternal_id

–> ipv resDb!External_id

In mijn applicatie deed ik eerst een controle op het bestaan van het order, waarbij die loadFromDb code gebruikt werd.

Verder had ik die load code nog nooit gebruikt (applicatie is nog in ontwikkeling), dus ik was die fout nooit tegengekomen.

Deze fout kan normaal niet voorkomen want ik maak altijd eerst de velden in de databank aan, en genereer daarna de persistence code met de dbInfoCode tool.

Dit veld was nadien toegevoegd, en deze lijn manueel toegevoegd. In het vervolg ga ik langs die tool en knip/plak de gegenereerde code …

Null Object of Connection is not opened

Soms krijg je deze fout bij een databaseverbinding die niet werkt (bv omdat server niet bereikbaar is of de database niet gestart is op je dev station).

Mijn database code zit in een module, bv MData.
Ik gebruikte deze test:

Dim myResult As Result
'
Try myResult = MData.getAllLines()
'
If Error Then
  doLog(Error.Text)
Else
  If myResult.Available Then
    ... use data...
  Endif

Maar dat is niet genoeg; als de fout, zoals hier, in de MData gebeurt, krijg je toch een situatie waar de Try geen fout geeft, maar myResult NULL is, en het programma crasht op myResult.Available: NULL Object.

Dim myResult As Result
'
Try myResult = MData.getAllLines()
'
If Error Or (myResult = NULL) Then
  doLog(Error.Text)
Else
  If myResult.Available Then
    ... use data...
  Endif

Hier wordt de foutmelding: “Connection is not opened

Wat ook werkt:

Dim myResult As Result
'
Try myResult = MData.getAllLines()
'
If (myResult = NULL) Then
  doLog(Error.Text)
Else
  If myResult.Available Then
    ... use data...
  Endif

Hier wordt de foutmelding eveneens “Connection is not opened“.

Je slaat dan wel de test op If Error over, kan dat…

Als je bv verkeerdelijk een paramater meegeeft in
MData.getAllLines(invalidparemater)
krijg je daar een foutmelding over: “Too many arguments“. Ja dus.

Bereik van variabelen als record id

Wanneer kies je in Gambas voor int, wanneer voor long?
Wanneer kies je in de databank voor een int(11), wanneer voor bigint(20)?

https://gambaswiki.org/wiki/lang/type

Kleinere:
Datatype Description Default value Size in memory
Boolean True or false. FALSE 1 byte
Byte 0...255 0 1 byte

Integer meer of minder:
Datatype Description Default value Size in memory
Short -32.768...+32.767 0 2 bytes
Integer -2.147.483.648...+2.147.483.647 0 4 bytes
Long -9.223.372.036.854.775.808...+9.223.372.036.854.775.807 0 8 bytes

Ik merk dat ik uit luiheid meestal “int” gebruik. Dikwijls is dat overkill, en is Short zeker genoeg. En als er geen negatieve getallen kunnen voorkomen (soms wordt een fout aangeduid door een negatief getal), en het maar over een klein getal gaat, dan is Byte zelfs genoeg.
Bij int is het vooral opletten met de grenzen als het bv record nummers woden; 2 miljoen records is niet zo veel.

MariaDB datatypes
MySQL datatypes, bv de integer data types :

Vereiste opslag en bereik van integer data types in MySQL

Type Opslag (Bytes) Minimum waarde Signed Minimum waarde Unsigned Maximum waarde Signed Maximum waarde Unsigned
TINYINT 1 -128 0 127 255
SMALLINT 2 -32768 0 32767 65535
MEDIUMINT 3 -8388608 0 8388607 16777215
INT 4 -2147483648 0 2147483647 4294967295
BIGINT 8 -263 0 263-1 264-1

Zie ook de tabel voor het doen overeenkomen van een type in de programmeertaal naar de databank, db-type mapping:

https://gambaswiki.org/wiki/doc/db-type-mapping

Datums, databanken en Gambas

Ik heb een paar keer problemen gehad met datum/tijd in Gambas, meestal gecombineerd met het opslaan in een databank, of er terug uit ophalen (*).

Bug
Op een bepaald moment werd er een bug gemeld op de mailinglist:

[Gambas Bug Tracker] Bug #1321: Converting date to string behavior change between 3.10 and 3.11

Gebruikers hadden ontdekt dat bepaalde programma’s, bepaalde broncode, niet meer werkte na een update van Gambas3 (overgang 3.10 naar 3.11 of hoger).

De bug-melding werd verworpen.

Correctie
Maar die verandering werd bevestigd; het was echter geen bug; ze was het gevolg van het verbeteren van een bug; er zat een fout in vroeger Gambas-code, en die was met deze versie-wissel gecorrigeerd, waardoor Gambas inderdaad anders reageert in sommige situaties.

Str() Val() Format() en Date() maken gebruik van de “locale”, de instellingen van de “desktop” (taal/land/tijd/etc).

CStr() gebruikt de UTC tijd.

Dus je moet kijken naar de instelling van de database en die van je desktop, bv GMT+0200.

In één programma CDate() en Date() mengen zal waarschijnlijk problemen geven.

De interne manier om een datum of tijd bij te houden is een getal, relatief tov een denkbeeldig nulpunt.

Met Format(), Date() maak je een interpretatie waarin je tijdzone meegenomen wordt om het voor jou “aanschouwelijk juist” te maken.

Bv in Groot-Brittanië is een datum/tijd opgeslagen in een record.
Als jij die opvraagt en toont met Format() dan krijg je de tijd die het in jouw tijdszone was, niet wat letterlijk opgeslagen is in de database.

Je moet dus ook opletten (voor het verschil)
– of je de database een datum laat opslaan, bv automatisch (instelling db server) met de instelling timestamp.
– of je zelf een datum naar de database stuurt als tekst: .. values('2024-01-01 01:14:18')
– of je kan in je SQL statement de opdracht voor een datum geven

Database
De database (mysql/mariadb) heeft 5 tijdsgebonden opslagvormen (kolom):

  • DATE = aleen de datum (1000-01-01-9999-12-31)
  • DATETIME = datum + tijd (1000..:..- 9999...:..)
  • TIMESTAMP datum + tijd (1970-20238!!!!)
  • YEAR : alleen een jaartal (1901-2155)
  • TIME : alleen een tijd (getal -838.. tot + 838.. ong 35 dagen)

Het 2038 probleem

Het hangt er natuurlijk een beetje vanaf wat je met die datums wil doen, en daarom moet je rekening houden met hun bereik, meestal vooral met hun hoogst mogelijke waarde, die voor sommige formaten gevaarlijk dichtbij komt.

Als je de datum enkel opslaat als leesbare informatie voor de programmeur, is 2038 van timestamp geen probleem, maar als het een veld is waar je verder conclusies uit gaat trekken gebaseerd op vergelijkingen met andere datum/tijd, berekeningen maken, sorteren enz, dan zie je de problemen al opduiken nog voor je op pensioen* bent. En timestamp is ook zuiniger met opslagruimte.
(* bv als je geboren bent na de default pc BIOS datum van 04-01-1980)

DATETIME is dus het veiligere alternatief, maar let op met de tijdszone.
Timestamp probeert de “huidige” tijdszone om te zetten naar UTC om de waarde op te slaan in de database, en terug te zetten naar de tijdszone (van de server**) bij het opvragen.
** dus niet de zone van de client als je bv vanop afstand gegevens opvraagt

Tijdzone
Vanaf Gambas 3.18 kan de tijdzone meegegeven worden:
(Old date string representation) space [ UTC | GMT ] [ + | - ] HH [ :MM ]

Om de algehele verwarring rond datums, (interne) opslag en weergave, tijdzone en formaten aan te pakken werd deze wiki pagina gemaakt, met oa:

Datums zijn geen strings
– Interne voorstelling
– Functies die werken met U.T.C. en American date format
– Functies die werken met local time
– Impliciete omvorming
– Datums zijn getallen
Null datums en datums met alleen een tijdsdeel
– Datums bewaren
– Datums bewaren in een binair bestand
– Datums bewaren in een tekstbestand
– Datums en kalenders

Voor selectie van een datum, zie ook de wiki pagina over kalenders.

Bronnen
– mailinglist en bugtracker
https://lists.gambas-basic.org/pipermail/user/2018-May/064153.html
Datetimes versus timestamps in MySQL
https://gambaswiki.org/ wiki/doc/date, wiki/doc/calendar

Testen in Gambas met unittesting

Testen

Ik gebruikte al verschillende manieren om mijn programma’s te testen:
– ik dump allerlei waarden naar de output met print (die blijven ook werken in uitvoerbare programma’s)
– ik dump allerlei waarden naar de output met debug (die worden er uit gehaald bij compileren als je dat kiest)
– ik neem testcode op in mijn applicatie en stuur de uitvoer naar een optioneel zichtbaar te maken “log” (bestand of tekst op scherm).
– bij libraries schreef ik de testen in de main module, omdat die toch niet geëxporteerd wordt, dus niet zichtbaar wordt voor gebruikers. Wordt snel te veel.
– ik maak een aparte module “MTest” waar ik alle tests in steek. Ik moet die dan nog wel aanroepen uit bv de Main (library) of kan ze zelfs vanuit mijn draaiende applicatie aanroepen (bv via een testmenu in “hidden developer mode”).
– ik schreef een library MijnLib en maakte een testprogramma MijnLibTest en riep de testen aan vanuit Main, en zet ze aan of af door een commentaarteken voor de lijn te wissen/zetten. Wordt ook snel onoverzichtelijkt.
Maar dat is nog geen unittesten

Formeel geÏntegreerd
Zoals altijd bij Gambas (althans mijn ervaring): als je iets nodig hebt, blijkt het ofwel al te bestaan, ofwel wordt het bijgemaakt, en kan je je eigen methodes vervangen door de geïntegreerde methodes in Gambas zelf.

Bij gebruik van de Gambas3 IDE viel me op dat er bij creatie van een nieuw bestand onder “bronnen”, behalve de opties “map”, “klasse”, en “module”, ook een optie “Test module” bestaat. Die maakt standaarde de testmodule “Test1” aan (die als bestandsnaam “Test1.test” heeft).
Waarschijnlijk is het overzichtelijker om een map te maken voor je tests (zoals ze in het voorbeeld doen); dus maak je eerst submap “Test”, en daarin de “Test1.test”. De testbestanden worden gebruikt in volgorde van hun bestandsnaam, en binnenin op volgorde van de methodenamen.
Een testmodule is in de linkse kolom herkenbaar aan een iets ander icoontje: een optionbox (aanvinkbaar hokje), en bij conventie laat je de naam voorafgaan door een T: TNaam (vgl module MNaam, form FNaam, class CNaam)

In de programmeeromgeving van Gambas3 druk je op F4 om de testen te starten.
Onderaan krijg je een vensterdeel met de resultaten van de tests. Bij het uitvoeren van de tests wordt een teller bijgehouden en onderaan krijg je een resultaat, bv als alles goed ging “PASSED”, anders “FAILED”.

Om de testen op te stellen heb je “Assert” te hulp:

Assert.Equals(uitdrukking1, uitdrukking2, commentaar)
Assert.Ok(uitdrukkingIsTrueOrNot, commentaar)
Assert.Error(commentaarBijErrorInTry_Something)
enz, Assert heeft een heleboel nuttige tests.

Gebruik
Als je helemaal nog geen code hebt, en gewooen een nieuwe test maakt “Test1”, en je probeert F4 krijg je:

1..0

# Ran ‘Test1’
#
# FAILED

En de voorbeeldcode (zie link onderaan) draait een succesvolle test en geeft:

1..5

Test THello.AHelloWorld
# I am the first test, because my name starts with A.
ok 1 – THello.AHelloWorld.7: HW strings should be equal
1..1
ok 1 – THello.AHelloWorld
(…enz 2, 3, 4 ..)
Test THello.Right
ok 1 – THello.Right.19: Hello.Right says Right
1..1
ok 5 – THello.Right

# Ran ‘Testsuite: A: Run all tests’
#
# PASSED

Verfijnen
Als je wil kunnen kiezen welke tests je wel of niet draait, kan je “test suites” maken. In het test scherm (F4) krijg je rechts onderaan de knop om “Test suites” te maken, -draaien, -beheren, enz.

Plannen
Het is lonend om bij het programmeren voor bepaalde methodes/procedures/functies eerst de test te programmeren, en dan pas de methode zelf: je kan dan tijdens het programmeren van de methode onmiddellijk testen met je test.
Als je later aanpassingen aan je programma maakt, bedenk je eerst of de test moet veranderen, en daarna kan je de wijzigingen dan ook testen met je oorspronkelijke of aangepaste test.
Vooral bij libraries zijn testmodules interressant, ook voor algemene code in modules in je project.

Links
https://gambaswiki.org/wiki/doc/unittesting
https://nl.wikipedia.org/wiki/Unittesten
https://gitlab.com/gambas/gambas/-/blob/master/main/lib/test/gb.test/unittesthelloworld-1.0.0.tar.gz

Gambas compatibiliteit (backward compatibility): soms niet

Als je broncode schrijft in Gambas versie 3.(x) dan kan het zijn dat die niet werkt in versie 3.(x-1) https://gambaswiki.org/wiki/doc/compat
Als het een voorwaarde is dat die code daar wel werkt moet je weten wat niet gebruikt mag worden uit de mogelijkheden van je nieuwere Gambas versie.
Hieronder begin ik een lijstje met zelf ondervonden incompatibiliteit, als ik een officiële Gambas pagina vindt daarover komt die hier in de plaats…

Als je weet waar in je code het probleem ontstaat op de oude versie, kan je daar “TRY” gebruiken:
Use TRY and check for an ERROR to see if newer code will work on the current version of gambas or not.

Settings.Exist : code gemaakt in 3.18.4 – code werkt niet in: 3.9.1

with / end with : nesten van twee strukturen in elkaar werkt niet in oude Gambas versies.

with myClass
  with myObject
    ' code code..
  end with
end with

Form elementen : bepaalde eigenschap bestaat niet in oude versie/andere desktop (Gnome):
ScrollView.Autoresize

Vriendelijk afsluiten van je programma

Een voorbeeldje van wat in mijn MMain zit bij een programma met meer vensters
(in de Gambas IDE zijn dat de Forms):

Public Sub doQuit()
  '
  Dim hWindow As Window
  '
  Settings.Save  ' other code 
  hRunCounter.appClose() ' other code
  For Each hWindow In Windows
    hWindow.Close
  Next
  '
End

Other code:
Settings.Save: omdat ik de component Settings gebruikt.
hRunCounter: ik hou een teller bij van het starten en sluiten van het programma