Ubuntu 12.04 Postgres Access for C

Ubuntu 12.04 Postgres Access for C

Description

This post describes the steps to install the software needed:

  • to be able to access a PostgreSQL database table from C,
  • starting from a DigitalOcean Ubuntu 12.04 Droplet, Virgin Image.

Step 1 Create DigitalOcean Ubuntu 12.04 Droplet

  • Log into DigitalOcean (DO) Droplets
  • Click the “Create Droplet” Button at the top right.
  • Name your Droplet Hostname. Select Size. Select Region.
  • Select Image, On “Distributions Tab”/UbuntuTile_bottom_half, click & select “12.04.05 x32”
  • Click Big Green Button at bottom “Create Droplet”
  • Copy the Droplet ip address for later access.

Step 2 Install PostgreSQL on Ubuntu 12.04

I follow “How To Install and Use PostgreSQL on Ubuntu 12.04”.

root@whatever:~# # logged in as root
root@whatever:~#
root@whatever:~# apt-get update

[**DELETED LINES**]

Reading package lists... Done

root@whatever:~#
root@whatever:~# # download Postgres and its helpful accompanying dependencies
root@whatever:~# sudo apt-get install postgresql postgresql-contrib

Reading package lists... 0%

[**DELETED LINES**]

Moving configuration file /var/lib/postgresql/9.1/main/pg_ident.conf to /etc/postgresql/9.1/main...
Configuring postgresql.conf to use port 5432...
update-alternatives: using /usr/share/postgresql/9.1/man/man1/postmaster.1.gz to provide /usr/share/man/man1/postmaster.1.gz (postmaster.1.gz) in auto mode.
* Starting PostgreSQL 9.1 database server
[ OK ]
Setting up postgresql (9.1+129ubuntu1) ...
Setting up postgresql-contrib-9.1 (9.1.15-0ubuntu0.12.04) ...
Setting up postgresql-contrib (9.1+129ubuntu1) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

Step 3 Add a new [Linux] User

The "How To Install and Use PostgreSQL on Ubuntu 12.04" article says the next step is to "Create Your PostgreSQL Roles and Databases".

However, first, before that, I will add a new [non root, Linux] User, since this is a virgin image and I don't want to be messing around in root all the time.

I will however, give the new user Admin Privileges.

root@whatever:~# # Joe's first step is to add a new [Linux] user.
root@whatever:~# #     now following https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo- privileges-to-users-on-a-debian-vps
root@whatever:~# #         assume you are currently logged in as the root user, pwd == ~
root@whatever:~#
root@whatever:~# adduser joed   # or whatever username you want

[**DELETED LINES** you get asked a lot of questions in here]

Is the information correct? [Y/n]
root@whatever:~# su - joed   # www.linfo.org/su.html says "The su (short for substitute user)..."
joed@whatever:~$ pwd
/home/joed
joed@whatever:~$ exit  # exit from joed goes back to root
logout
root@whatever:~# pwd
/root

Step 4 Grant [Linux] Users Administrative Privileges

I want the newly added Linux user, "joed", to have Administrative Privileges.

root@whatever:~#
root@whatever:~# # Grant Users Administrative Privileges
root@whatever:~# #    enable sudo privileges
root@whatever:~# #        run the   visudo   command
root@whatever:~# #            i set visudo command editor to be nano  - i hate vi
root@whatever:~# # see http://superuser.com/a/821888/236556
root@whatever:~# # using WinSCP & np++ i edited /etc/sudoers  DIRECTLY, adding the following lines under the Defaults section at the beginning
root@whatever:~# #    Defaults        editor="/usr/bin/nano"
root@whatever:~#
root@whatever:~#
root@whatever:~# # now using visudo [with nano] i add the following line
root@whatever:~# #    joed    ALL=(ALL:ALL) ALL
root@whatever:~# #    under these 2 lines
root@whatever:~# #    # User privilege specification
root@whatever:~# #    root    ALL=(ALL:ALL) ALL
root@whatever:~#
root@whatever:~# #    N.B. i used the visudo command instead of editing it directly with np++
root@whatever:~# #        because i read SOMEPLACE?? that visudo checks the syntax of the lines for correctness
root@whatever:~#
root@whatever:~#
root@whatever:~#
root@whatever:~# # now let's check to see if joed has sudo priveleges
root@whatever:~#
root@whatever:~# su joed
joed@whatever:/root$
joed@whatever:/root$
joed@whatever:/root$ # check if i have sudo priveleges
joed@whatever:/root$     # see http://superuser.com/a/553939/236556
joed@whatever:/root$
joed@whatever:/root$ sudo -v
[sudo] password for joed:
joed@whatever:/root$ sudo -l
Matching Defaults entries for joed on this host:
env_reset, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, editor=/usr/bin/nano

User joed may run the following commands on this host:
(ALL : ALL) ALL
joed@whatever:/root$ exit
exit
root@whatever:~#
root@whatever:~#
root@whatever:~# # OK joed is a new Linux user  &  has sudo priveleges.
root@whatever:~#

Step 5 Make the new Linux User a PostgreSQL "superuser".

Now we "pop the stack" back into "How To Install and Use PostgreSQL on Ubuntu 12.04" at the "Create Your PostgreSQL Roles and Databases" step.

Remember, in the big picture, we are making the Linux user, joed, become a PostgreSQL superuser & accessing a PostgreSQL table from the C language.

root@whatever:~#
root@whatever:~#
root@whatever:~# # Create Your PostgreSQL Roles and Databases
root@whatever:~# #    To begin creating custom users, first switch into the [PostgreSQL] default [Linux] user [== "postgres"]
root@whatever:~# sudo su - postgres      # i BELIEVE i don't need sudo because i am doing this as root but WHY NOT FOLLOW THE DIRECTIONS  🙂
postgres@whatever:/root$
postgres@whatever:/root$ cd ~
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ # OK so we are in the Linux user account named postgres, added by the PostgreSQL install
postgres@whatever:~$ #     now we will do a PostgreSQL createuser command  to make the existing Linux user, joed, be a PostgreSQL superuser
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ pwd
/var/lib/postgresql
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ createuser --pwprompt
Enter name of role to add: joed
Enter password for new role:  <enter the pw>
Enter it again: <enter the pw>
Shall the new role be a superuser? (y/n) y
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ # now let's look for joed in the pg database
postgres@whatever:~$
postgres@whatever:~$ psql
psql (9.1.15)
Type "help" for help.

postgres=# \dt
No relations found.
postgres=# \l
List of databases
Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
(3 rows)

postgres=# \du-- show users
postgres=# \du
List of roles
Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
joed      | Superuser, Create role, Create DB, Replication | {}
postgres  | Superuser, Create role, Create DB, Replication | {}

postgres=# -- N.B. -- is the psql  COMMENT indicator
postgres=# -- list databases & tables for current db  http://dba.stackexchange.com/a/1288
postgres=# --     also above tells how to switch the currnent db
postgres=# -- OK logout of the psql interpreter (\q) & exit back to root Linux user & log back in as postgres_user joed Linux
postgres=# \q
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ exit
exit
root@whatever:~#
root@whatever:~# # OK joed is a PostgreSQL superuser

Step 6 Create a PostgreSQL Database

I am going to create a PostgreSQL database named "omnia". I will do this as the PostgreSQL user named "postgres".

N.B We are back into "How To Install and Use PostgreSQL on Ubuntu 12.04" at the "Create Your PostgreSQL Roles and [now] Databases" step.

root@whatever:~#
root@whatever:~# # ok [from root] log back in as Linux user == postgres
root@whatever:~# su postgres
postgres@whatever:/root$ cd ~
postgres@whatever:~$ # re-follow https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-12-04
postgres@whatever:~$ # create your first usable postgres database
postgres@whatever:~$ #    i create a named "omnia"
postgres@whatever:~$ createdb omnia
postgres@whatever:~$
postgres@whatever:~$
postgres@whatever:~$ psql
psql (9.1.15)
Type "help" for help.

postgres=# \l
List of databases
Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
omnia     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
(4 rows)

postgres=# -- -- http://stackoverflow.com/questions/3949876/how-to-switch-databases-in-psql
postgres=# \connect omnia
You are now connected to database "omnia" as user "postgres".
omnia=# \q
postgres@whatever:/root$ # let's try this as joed
postgres@whatever:/root$ exit
exit
root@whatever:~# su joed
joed@whatever:/root$ cd ~
joed@whatever:~$ pwd
/home/joed
joed@whatever:~$ # follow https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-12-04
joed@whatever:~$     # log into the correct database==omnia(using the psql -d omnia)
joed@whatever:~$ psql -d omnia
psql (9.1.15)
Type "help" for help.

omnia=# -- YAHOO we're in as joed a postgres superuser
omnia=# \l
List of databases
Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
omnia     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
|          |          |             |             | postgres=CTc/postgres
(4 rows)

omnia=# \du
List of roles
Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
joed      | Superuser, Create role, Create DB, Replication | {}
postgres  | Superuser, Create role, Create DB, Replication | {}

omnia=# \q
joed@whatever:~$
joed@whatever:~$ pwd
/home/joed

Step 7 Create & Initialize a Table

I will create the table named "test.

I will initialize (load it up) from a .csv file.

I will do this as the [Linux & PostgreSQL] user named "joed".

[joed@whatever trial_test_matrix]$ # now let's make the table named "test" in the "omnia" db
[joed@whatever trial_test_matrix]$ psql -d omnia
psql (9.1.15)
Type "help" for help.

omnia=# CREATE TABLE test(
omnia(#     id INTEGER PRIMARY KEY,
omnia(#     test_ix INTEGER,
omnia(#     origin CHAR(512),
omnia(#     max_prime INTEGER,
omnia(#     primes_tail_0 INTEGER,
omnia(#     primes_tail_1 INTEGER,
omnia(#     primes_tail_2 INTEGER,
omnia(#     primes_tail_3 INTEGER,
omnia(#     primes_tail_4 INTEGER,
omnia(#     primes_tail_5 INTEGER,
omnia(#     primes_tail_6 INTEGER,
omnia(#     primes_tail_7 INTEGER
omnia(# );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE
omnia=# \dt
List of relations
Schema | Name | Type  | Owner
--------+------+-------+-------
public | test | table | joed
(1 row)

omnia=# -- show the column names for test
omnia=# \d test

Table "public.test"
Column     |      Type      | Modifiers
---------------+----------------+-----------
id            | integer        | not null
test_ix       | integer        |
origin        | character(512) |
max_prime     | integer        |
primes_tail_0 | integer        |
primes_tail_1 | integer        |
primes_tail_2 | integer        |
primes_tail_3 | integer        |
primes_tail_4 | integer        |
primes_tail_5 | integer        |
primes_tail_6 | integer        |
primes_tail_7 | integer        |
Indexes:
"test_pkey" PRIMARY KEY, btree (id)

omnia=# \q
[joed@whatever trial_test_matrix]$ # now load up the omnia.test table from init.dbcsv []n]o] ]h]e]a]d]e]r]s]
[joed@whatever trial_test_matrix]$
[joed@whatever trial_test_matrix]$ psql -d omnia
psql (9.1.15)
Type "help" for help.

omnia=# -- now import from csv
omnia=# --    see http://stackoverflow.com/a/2987451/601770
omnia=# --    we will do something like COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV;
omnia=# --    COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV;test/home/joed/expr/trial_test_matrix/init.csv
omnia=# -- load up the table from init.csv file NO HEADER, 1000 records
omnia=# COPY test FROM '<path to>/init.csv' DELIMITER ',' CSV;
COPY 1000
omnia=# -- yahoo
omnia=#
omnia=# SELECT test_ix, max_prime FROM test WHERE id<20;

test_ix | max_prime
---------+-----------
0 |       840
1 |       980
2 |       900
3 |       900
4 |       830
5 |       950
6 |       990
7 |       800
8 |       960
9 |       820
10 |       910
11 |       930
12 |       920
13 |       950
14 |       960
15 |       820
16 |       830
17 |       880
18 |       830
(19 rows)

omnia=# \q

[joed@whatever trial_test_matrix]$ # OK we have created a table named test
[joed@whatever trial_test_matrix]$ #      AND loaded it up with data from a .csv file

Step 8 Install gcc (the C compiller)

Aparently, gcc does not come with the standard DO Ubuntu image. Who'd 'a thunk it? 🙂

I'll install it as root.

[joed@whatever SQL]$
[joed@whatever SQL]$ # The tale of "woe" begins here. 🙂
[joed@whatever SQL]$
[joed@whatever SQL]$ # Try to compile my C program named tse_analogous_db.c
[joed@whatever SQL]$ #    located in the   .../SQL dir
[joed@whatever SQL]$
[joed@whatever SQL]$ gcc -c -I/usr/local/pgsql/include  tse_analogous_db.c
The program 'gcc' can be found in the following packages:
* gcc
* pentium-builder
Ask your administrator to install one of them
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # well that does that   -- i have to install gcc
[joed@whatever SQL]$ # see http://askubuntu.com/a/271561/144883
[joed@whatever SQL]$ #     via the toolchain PPA
[joed@whatever SQL]$ #          add the PPA to your system
[joed@whatever SQL]$ # i am going to do this as root
[joed@whatever SQL]$
[joed@whatever SQL]$ exit
root@whatever:~#
root@whatever:~# # OK now let's install gcc according to  http://askubuntu.com/a/271561/144883  - REALLY
root@whatever:~# #    via the toolchain PPA
root@whatever:~# #          add the PPA to your system
root@whatever:~#
root@whatever:~# # First command listed by the link i am following:
root@whatever:~# #    http://askubuntu.com/a/271561/144883
root@whatever:~# #        apt-get install python-software-properties
root@whatever:~#
root@whatever:~# apt-get install python-software-properties

Reading package lists... 0%
[**DELETED LINES**]
After this operation, 651 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
[**DELETED LINES**]
Setting up python-software-properties (0.82.7.7) ...
root@whatever:~#
root@whatever:~#
root@whatever:~# # Next command listed by the link i am following:
root@whatever:~# #    http://askubuntu.com/a/271561/144883
root@whatever:~# #        add-apt-repository ppa:ubuntu-toolchain-r/test
root@whatever:~#
root@whatever:~#
root@whatever:~# add-apt-repository ppa:ubuntu-toolchain-r/test
You are about to add the following PPA to your system:
Toolchain test builds; see https://wiki.ubuntu.com/ToolChain

More info: https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpNRzYg4/secring.gpg' created
[**DELETED LINES**]
gpg:               imported: 1  (RSA: 1)
OK
root@whatever:~#
root@whatever:~#
root@whatever:~#
root@whatever:~# # Next command listed by the link i am following:
root@whatever:~# #    http://askubuntu.com/a/271561/144883
root@whatever:~# #        apt-get update
root@whatever:~#
root@whatever:~# apt-get update


0% [Working]
[**DELETED LINES**]
Reading package lists... Done

root@whatever:~#
root@whatever:~#
root@whatever:~#
root@whatever:~#
root@whatever:~# # Next command listed by the link i am following:
root@whatever:~# #    http://askubuntu.com/a/271561/144883
root@whatever:~# #        apt-get install gcc-4.8
root@whatever:~#
root@whatever:~# #    The above link ALSO says
root@whatever:~# #        The latest available version of gcc, for 12.04, is 4.8.1 and is available in the toolchain PPA
root@whatever:~#
root@whatever:~# apt-get install gcc-4.8.1

Reading package lists... 0%
[**DELETED LINES**]
After this operation, 70.6 MB of additional disk space will be used.
Do you want to continue [Y/n]? y
[**DELETED LINES**]
Setting up manpages-dev (3.35-0.1ubuntu1) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
root@whatever:~#
root@whatever:~#
root@whatever:~#
root@whatever:~# # Next is the FINAL command listed by the link i am following:
root@whatever:~# #    http://askubuntu.com/a/271561/144883
root@whatever:~# #        update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
root@whatever:~#
root@whatever:~# update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
root@whatever:~#
root@whatever:~#
root@whatever:~# # OK gcc is now installed 🙂
root@whatever:~#

Step 9 Install libpq-dev to access PostgreSQL from C

The libpq-dev code library for accessing PostgreSQL from C needs to be installed.

I'll install it as root.

root@whatever:~#
root@whatever:~# su joed
joed@whatever:/root$ # shorten the prompt
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # install libpq-dev
[joed@whatever SQL]$ # Following http://askubuntu.com/a/182062/144883
[joed@whatever SQL]$ # Do this as root
[joed@whatever SQL]$ exit
exit
[root@whatever ~]#
[root@whatever ~]# apt-get install libpq-dev

Reading package lists... 0%
[**DELETED LINES**]
After this operation, 9,328 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
[**DELETED LINES**]
Setting up libpq-dev (9.1.15-0ubuntu0.12.04) ...
Setting up libssl-doc (1.0.1-4ubuntu5.27) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
[root@whatever ~]#
[root@whatever ~]#
[root@whatever ~]# # OK Looks like libpq-dev is installed.
[root@whatever ~]# # Lets see if we hav been successful
[root@whatever ~]# #    Go back to joed.
[root@whatever ~]#
[root@whatever ~]# su joed
[joed@whatever ~]$ cd [path to SQL dir ie whatever dir has your C code in it]
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # Via WinSCP, I changed all permissions recursively to 755 Group: joed [1000] Owner: joed [1000] in [path to]/trial_test_matrix
[joed@whatever SQL]$ # see: http://www.postgresql.org/docs/9.1/interactive/auth-methods.html#AUTH-TRUST
[joed@whatever SQL]$ # see  http://www.postgresql.org/docs/9.3/static/libpq-connect.html
[joed@whatever SQL]$ #     added joed's pw for the omnia db to the connect string in tse_analogous_db.c
[joed@whatever SQL]$
[joed@whatever SQL]$ # OK lets Compile, Link & run tse_analogous_db
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # Compile tse_analogous_db.c
[joed@whatever SQL]$ gcc -c  -I/usr/include/postgresql  tse_analogous_db.c
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # Link tse_analogous_db.o into tse_analogous_db.exe
[joed@whatever SQL]$ gcc -o tse_analogous_db.exe tse_analogous_db.o -L/usr/lib -lpq
[joed@whatever SQL]$
[joed@whatever SQL]$
[joed@whatever SQL]$ # Run tse_analogous_db.exe
[joed@whatever SQL]$ ./tse_analogous_db.exe
datname        datdba         encoding       datcollate     datctype       datistemplate  datallowconn   datconnlimit   datlastsysoid  datfrozenxid   dattablespace  datacl

template1      10             6              en_US.UTF-8    en_US.UTF-8    t              t              -1             11942          706            1663           {=c/postgres,postgres=CTc/postgres}
template0      10             6              en_US.UTF-8    en_US.UTF-8    t              f              -1             11942          706            1663           {=c/postgres,postgres=CTc/postgres}
postgres       10             6              en_US.UTF-8    en_US.UTF-8    f              t              -1             11942          706            1663
omnia          10             6              en_US.UTF-8    en_US.UTF-8    f              t              -1             11942          706            1663


joe_t1 begin
id             test_ix        origin         max_prime      primes_tail_0  primes_tail_1  primes_tail_2  primes_tail_3  primes_tail_4  primes_tail_5  primes_tail_6  primes_tail_7

17             16             Aberdeen                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        830            0              0              0              0              0              0              0              0
func: func_uses_DAL_sub0, test_index: 0


func_uses_DAL_sub0.PQntuples(res): 1


[joed@whatever SQL]$
[joed@whatever SQL]$ # yahhoo SUCCESS
[joed@whatever SQL]$

Thus Endeth the Lesson 🙂

Love and peace,

Joe

Advertisements

Updated web2py DAL Basic Examples

DAL Updated Examples

Content

Table: Define [a Table], Insert, Select, Update, Count, Delete, Drop [a Table]

Also See in the web2py Book:

# make this function now for later result printing
def p(rows):
    for r in rows:
        print r.name, r.addr, r.city

# Content: Define, Insert, Select, Update, Count, Delete, Drop

# Define [a Table]
db.define_table('person', Field('name'), Field('addr'), Field('city') )   # person has 4 fields person.id + person.name .addr .city

# Insert
db.person.insert( **{'name':'joe', 'addr':'5 Blue St', 'city':'waco'} )
db.person.insert( **{'name':'jim', 'addr':'6 Red St', 'city':'waco'} )
db.person.insert( **{'name':'john', 'addr':'7 Green St', 'city':'waco'} )
db.person.insert( **{'name':'jack', 'addr':'7 Green St', 'city':'houston'} )
db.person.insert( **{'name':'jackie', 'addr':'7 Green St', 'city':'houston'} )
db.person.insert( **{'name':'jill', 'addr':'7 Green St', 'city':'austin'} )
db.person.insert( **{'name':'jane', 'addr':'9 Brown St', 'city':'austin'} )


# Select        
# select all rows in person
rows = db(db.person.id > 0).select()
In [55]: p(rows)
joe 5 Blue St waco
jim 6 Red St waco
john 7 Green St waco
jack 7 Green St houston
jackie 7 Green St houston
jill 7 Green St austin
jane 9 Brown St austin

# select rows in city is waco
rows = db(db.person.city == 'waco').select()
In [61]: p(rows)
joe 5 Blue St waco
jim 6 Red St waco
john 7 Green St waco

# select rows in city is 'waco' AND addr is '7 Green St'
rows = db( (db.person.city == 'waco') & (db.person.addr == '7 Green St') ).select()
In [73]: p(rows)
john 7 Green St waco

# select rows in city is 'houston' OR name is 'joe'
rows = db( (db.person.city == 'houston') | (db.person.name == 'joe') ).select()
In [83]: p(rows)
joe 5 Blue St waco
jack 7 Green St houston
jackie 7 Green St houston

# Update  ->   get an id;   do the update
# update 1    update spelling jackie's name to 'jaquay'
id = db( (db.person.name=='jackie') & (db.person.addr=='7 Green St') & (db.person.city=='houston') ).select().first().id 
rtn = db.person[id] = dict(name='jaquay', addr='7 Green St', city='houston')

# update 1 result
In [87]: rtn
Out[87]: {'addr': '7 Green St', 'city': 'houston', 'name': 'jaquay'}
In [88]: rows = db(db.person.id > 0).select()
In [89]: p(rows)
joe 5 Blue St waco
jim 6 Red St waco
john 7 Green St waco
jack 7 Green St houston
jaquay 7 Green St houston
jill 7 Green St austin
jane 9 Brown St austin

# update 2    all '7 Green St's in 'houston' to '7 Yellow St' in 'houston'
rows = db( (db.person.addr=='7 Green St') & (db.person.city=='houston') ).select()
for row in rows:
    rtn = db.person[row.id] = dict(addr='7 Yellow St', city='houston')
    print rtn
# update 2 result
rows = db(db.person.id > 0).select()
In [94]: p(rows)
joe 5 Blue St waco
jim 6 Red St waco
john 7 Green St waco
jack 7 Yellow St houston
jaquay 7 Yellow St houston
jill 7 Green St austin
jane 9 Brown St austin


# Count

# count 1    items in city is 'houston' OR name is 'joe'
In [97]: print db( (db.person.city == 'houston') | (db.person.name == 'joe') ).count()
3
# notice relationship to .select()
In [98]: print db( (db.person.city == 'houston') | (db.person.name == 'joe') ).select()
person.id,person.name,person.addr,person.city
1,joe,5 Blue St,waco
4,jack,7 Yellow St,houston
5,jaquay,7 Yellow St,houston

# count 2    items where name startswith 'ja'
In [99]: print db( (db.person.name.startswith('ja'))  ).count()
3
In [100]: print db( (db.person.name.startswith('ja'))  ).select()
person.id,person.name,person.addr,person.city
4,jack,7 Yellow St,houston
5,jaquay,7 Yellow St,houston
7,jane,9 Brown St,austin

# Delete   delete all items where name startswith('jo')  notice similarity to select()

rtn = db( (db.person.name.startswith('jo'))  ).delete()
In [105]: print rtn
2
rows = db(db.person.id > 0).select()
In [107]: p(rows)
jim 6 Red St waco
jack 7 Yellow St houston
jaquay 7 Yellow St houston
jill 7 Green St austin
jane 9 Brown St austin


# Drop [a Table]   drop the table from the db
db.person.drop()


see_also = '''
[Other operators](http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Other-operators)
[Combining rows](http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Combining-rows)
[list:<type> and contains](http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#list--type--and-contains)
'''

web2py Field Exegesis

web2py Field Exegesis

Joe Dorocak aka Joe Codeswell has written working Python code examples exploring “fully qualified” web2py Field constructors.

I wrote this to turn the web2py book chapter on the Field constructor into working, “fully qualified” examples, so I could understand the meaning and explore the features. There are 2 “fully qualified” examples in mytable for now:

  • fulldefaultstrfield – is my cut at fully qualifying the default settings for the Field constructor named parameters.
  • fullplay1strfield – is my 1st cut at playing around with the values of the named parameters in the Field constructor.

The results can be seen by implementing this locally and navigating to:

Content

  • In applications/fields/controllers/default.py
  • In applications/fields/models/db.py

In applications/fields/controllers/default.py

# -*- coding: utf-8 -*-
# In applications/fields/controllers/default.py

def gridmytable():
    grid = SQLFORM.grid(db.mytable)
    return locals()

In applications/fields/models/db.py

# -*- coding: utf-8 -*-
# In applications/fields/models/db.py

# web2py Field Exegesis
# Joe Dorocak aka Joe Codeswell has written working Python code examples exploring "fully qualified" web2py Field constructors. 
# I wrote this to turn the web2py book chapter on the Field constructor into working, "fully qualified" examples, so i could understand the meaning and explore the features. There are 2 "fully qualified" examples in mytable for now.
#  - fulldefaultstrfield - is my cut at fullyqualifying the default settings for the Field constructor named parameters.
#  - fullplay1strfield   - is my 1st cut at playing around with the values of the named parameters in the Field constructor.
# The results can be seen by implementing this locally and navigating to
#   -  inserting new records at   http://127.0.0.1:8000/fields/appadmin/select/db 
#   -  seeing the table grid at   http://127.0.0.1:8000/fields/default/gridmytable


# BOILERPLATE
if not request.env.web2py_runtime_gae:
    db = DAL('sqlite://storage.sqlite',pool_size=1,check_reserved=['all'])
else:
    db = DAL('google:datastore')
    session.connect(request, response, db=db)

response.generic_patterns = ['*'] if request.is_local else []

from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
auth = Auth(db)
crud, service, plugins = Crud(db), Service(), PluginManager()

## create all tables needed by auth if not custom tables
auth.define_tables(username=False, signature=False)
# END BOILERPLATE



# START HERE
db.define_table('mytable',

        Field('myfield','string'),

        # see http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Field-constructor
        # a fully defined field example that will HOPEFULLY work
        # Not all of the parameters are relevant for every field type.
        Field(
         'fulldefaultstrfield',        # Field name positional arg
          type='string',               # Field type see field_types below

          # Sets the maximum length of a "string", "password" or "upload" field.
          #     See "2.6.1 - 2.6.4" in  http://www.web2py.com/init/default/changelog
          #         "MySQL users: The length of string fields changed from 255 to 512 bytes. 
          length=512,       

          default='',                  # Default value used to pre-populate forms, can instead be a [lambda] function 
          required=False,              # True => A val for field MUST be specified at record insertion.
          requires=IS_LENGTH(512),     # Is a validator or a list of validators. see book /forms-and-validators#Validators. see field_types below    # joeNote: bad_value == '<DEFAULT>'
          ondelete='CASCADE',          # Defines actions on record delete. CASCADE => delete all referring records
          notnull=False,               # True => fulldeffield can't be Null at record insertion.
          unique=False,                # True => must be unique in the table [not quite the same as IS_NOT_IN_DB]
          uploadfield=True,            # Applies only to fields of type "upload" [Even though True is default and works for type=='string']. See upload_field_type_notes below

          # Must be one of the available widget objects, including custom widgets. 
          # Each field type has a default widget. See widgetList below   
          # This is default for fulldeffield.type=='string'          
          widget=SQLFORM.widgets.string.widget, 

          label=None,                  # Is a string (or a helper or something that can be serialized to a string) that contains the label to be used for this field in auto-generated forms.
                                       #     JoeNote: There's a diff between label=None => default label & label='' => NO LABEL SHOWN!
          comment='',                  # Is a string (or a helper or something that can be serialized to a string) that contains a comment associated with this field, and will be displayed to the right of the input field in the autogenerated forms. 
                                       #      JoeNote: No diff between comment='' & comment=None
          # If a field is neither readable nor writable, it will not be displayed in create and update forms.
          writable=True,               # Declares whether a field is writable in forms.
          readable=True,               # Declares whether a field is readable in forms.

          update=None,                 # Contains the default value for this field when the record is updated.

          authorize=None,              # For "upload" fields only, can be used to require access control on the corresponding field. See Authentication and also Authorization http://web2py.com/books/default/chapter/29/09/access-control.
          autodelete=False,            # For "upload" fields only, determines if the corresponding uploaded file should be deleted when the record referencing the file is deleted. 

          represent=None,              # Can be None or can point to a function that takes a field value and returns an alternate representation for the field value. See representation_examples below.         
          compute=None,                # See compute_notes below.

          uploadfolder=None,           # See upload_field_type_notes below
          uploadseparate=None,         # See upload_field_type_notes below
          uploadfs=None                # See upload_field_type_notes below
        ), 

        # joe says do a diff on following & above to hilight what changed
        #    i think i changed: fieldname, length, requires, label, comment, represent
        # need to provide insert & rendering actions to see diffs in result

        # see http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Field-constructor
        # a fully defined field example that will HOPEFULLY work
        # Not all of the parameters are relevant for every field type.
        Field(
         'fullplay1strfield',          # Field name positional arg
          type='string',               # Field type see field_types below

          # Sets the maximum length of a "string", "password" or "upload" field.
          #     See "2.6.1 - 2.6.4" in  http://www.web2py.com/init/default/changelog
          #         "MySQL users: The length of string fields changed from 255 to 512 bytes. 
          length=4096,       

          default='',                  # Default value used to pre-populate forms, can instead be a [lambda] function 
          required=False,              # True => A val for field MUST be specified at record insertion.
          requires=IS_LENGTH(4096),    # Is a validator or a list of validators. see book /forms-and-validators#Validators. see field_types below    # joeNote: bad_value == '<DEFAULT>'
          ondelete='CASCADE',          # Defines actions on record delete. CASCADE => delete all referring records
          notnull=False,               # True => fulldeffield can't be Null at record insertion.
          unique=False,                # True => must be unique in the table [not quite the same as IS_NOT_IN_DB]
          uploadfield=True,            # Applies only to fields of type "upload" [Even though True is default and works for type=='string']. See upload_field_type_notes below

          # Must be one of the available widget objects, including custom widgets. 
          # Each field type has a default widget. See widgetList below   
          # This is default for fulldeffield.type=='string'          
          widget=SQLFORM.widgets.string.widget, 

          label='lblPlay1strfield',    # Is a string (or a helper or something that can be serialized to a string) that contains the label to be used for this field in auto-generated forms.
                                       #     JoeNote: There's a diff between label=None => default label & label='' => NO LABEL SHOWN!
          comment='cmtPlay1strfield',  # Is a string (or a helper or something that can be serialized to a string) that contains a comment associated with this field, and will be displayed to the right of the input field in the autogenerated forms. 
                                       #      JoeNote: No diff between comment='' & comment=None
          # If a field is neither readable nor writable, it will not be displayed in create and update forms.
          writable=True,               # Declares whether a field is writable in forms.
          readable=True,               # Declares whether a field is readable in forms.

          update=None,                 # Contains the default value for this field when the record is updated.

          authorize=None,              # For "upload" fields only, can be used to require access control on the corresponding field. See Authentication and also Authorization http://web2py.com/books/default/chapter/29/09/access-control.
          autodelete=False,            # For "upload" fields only, determines if the corresponding uploaded file should be deleted when the record referencing the file is deleted. 

          # Can be None or can point to a function that takes a field value and returns an alternate representation for the field value. See representation_examples below.         
          # represent=lambda fullplay1strfield,row: fullplay1strfield.capitalize(),              
          #     result ticket: File "C:/web2py/applications/fields/models/db.py", line 194, in <lambda>
          #         represent=lambda fullplay1strfield,row: fullplay1strfield.capitalize(),
          #         AttributeError: 'NoneType' object has no attribute 'capitalize'
          #    it was None

          represent=lambda fullplay1strfield,row: fullplay1strfield.capitalize(),
          compute=None,                # See compute_notes below.

          uploadfolder=None,           # See upload_field_type_notes below
          uploadseparate=None,         # See upload_field_type_notes below
          uploadfs=None                # See upload_field_type_notes below
        ), 



    )



# see http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Field-types
field_types = '''
field_type              default_field_validators
string                  IS_LENGTH(length) default length is 512
text                    IS_LENGTH(65536)
blob                    None
boolean                 None
integer                 IS_INT_IN_RANGE(-1e100, 1e100)
double                  IS_FLOAT_IN_RANGE(-1e100, 1e100)
decimal(n,m)            IS_DECIMAL_IN_RANGE(-1e100, 1e100)
date                    IS_DATE()
time                    IS_TIME()
datetime                IS_DATETIME()
password                None
upload                  None
reference <table>     IS_IN_DB(db,table.field,format)
list:string             None
list:integer            None
list:reference <table>    IS_IN_DB(db,table.field,format,multiple=True)
json                    IS_JSON()
bigint                  None
big-id                  None
big-reference           None
'''

upload_field_type_notes = '''
    uploadfield:
        applies only to fields of type "upload". A field of type "upload" stores the name of a file saved somewhere else, by default on the filesystem under the application "uploads/" folder. If uploadfield is set to True, then the file is stored in a blob field within the same table and the value of uploadfield is the name of the blob field. This will be discussed in more detail later in the context of SQLFORM.
    uploadfolder:
        defaults to the application's "uploads/" folder. If set to a different path, files will uploaded to a different folder. For example,
            Field(...,uploadfolder=os.path.join(request.folder,'static/temp'))
        will upload files to the "web2py/applications/myapp/static/temp" folder.
    uploadseparate:
        if set to True will upload files under different subfolders of the uploadfolder folder. This is optimized to avoid too many files under the same folder/subfolder. ATTENTION: You cannot change the value of uploadseparate from True to False without breaking links to existing uploads. web2py either uses the separate subfolders or it does not. Changing the behavior after files have been uploaded will prevent web2py from being able to retrieve those files. If this happens it is possible to move files and fix the problem but this is not described here.
    uploadfs:
        allows you specify a different file system where to upload files, including an Amazon S3 storage or a remote SFTP storage. This option requires PyFileSystem installed. uploadfs must point to PyFileSystem. uploadfs
'''

widgetList = [
# See http://web2py.com/books/default/chapter/29/07/forms-and-validators?search=widgets#Widgets
# Here is a list of available web2py widgets:
    SQLFORM.widgets.string.widget,         # default for corresonding type
    SQLFORM.widgets.text.widget,           # default for corresonding type
    SQLFORM.widgets.password.widget,       # default for corresonding type
    SQLFORM.widgets.integer.widget,        # default for corresonding type
    SQLFORM.widgets.double.widget,         # default for corresonding type
    SQLFORM.widgets.time.widget,           # default for corresonding type
    SQLFORM.widgets.date.widget,           # default for corresonding type
    SQLFORM.widgets.datetime.widget,       # default for corresonding type
    SQLFORM.widgets.upload.widget,         # default for corresonding type
    SQLFORM.widgets.boolean.widget,        # default for corresonding type

    # The next 2 widgets are used when a field's requires is IS_IN_SET or IS_IN_DB
    # The "options" widget is used with multiple=False (default behavior), when a field's requires is IS_IN_SET or IS_IN_DB.
    SQLFORM.widgets.options.widget,
    # The "multiple" widget is used with multiple=True, when a field's requires is IS_IN_SET or IS_IN_DB. 
    SQLFORM.widgets.multiple.widget,

    # The "radio" and "checkboxes" widgets are never used by default, but can be set manually. 
    SQLFORM.widgets.radio.widget,    
    SQLFORM.widgets.checkboxes.widget,

    # See http://web2py.com/books/default/chapter/29/07/forms-and-validators?search=widgets#Autocomplete-widget
    SQLFORM.widgets.autocomplete,
    ]

representation_examples = '''
db.mytable.name.represent = lambda name,row: name.capitalize()
db.mytable.other_id.represent = lambda id,row: row.myfield
db.mytable.some_uploadfield.represent = lambda value,row:     A('get it', _href=URL('download', args=value))

"blob" fields are also special. 
By default, binary data is encoded in base64 before being stored into the actual database field, and it is decoded when extracted. 
This has the negative effect of using 25% more storage space than necessary in blob fields, but has two advantages. 
On average it reduces the amount of data communicated between web2py and the database server, and it makes the communication independent of back-end-specific escaping conventions.
'''    

compute_notes = '''
from http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Computed-fields
Computed fields

DAL fields may have a compute attribute. This must be a function (or lambda) that takes a Row object and returns a value for the field. When a new record is modified, including both insertions and updates, if a value for the field is not provided, web2py tries to compute from the other field values using the compute function. Here is an example:

>>> db.define_table('item',
        Field('unit_price','double'),
        Field('quantity','integer'),
        Field('total_price',
            compute=lambda r: r['unit_price']*r['quantity']))
>>> r = db.item.insert(unit_price=1.99, quantity=5)
>>> print r.total_price
9.95

Notice that the computed value is stored in the db and it is not computed on retrieval, as in the case of virtual fields, described later. Two typical applications of computed fields are:

    in wiki applications, to store the processed input wiki text as HTML, to avoid re-processing on every request
    for searching, to compute normalized values for a field, to be used for searching.

Computed fields are evaluated in the order in which they are defined in the table definition. A computed field can refer to previously defined computed fields (new after v 2.5.1)
Virtual fields

Virtual fields are also computed fields ...
    see: http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Virtual-fields
'''

grid_notes = '''

SQLFORM.grid signature
    http://web2py.com/books/default/chapter/29/07/forms-and-validators#SQLFORM-grid-signature

The complete signature for the grid is the following:

SQLFORM.grid(
    query,
    fields=None,
    field_id=None,
    left=None,
    headers={},
    orderby=None,
    groupby=None,
    searchable=True,
    sortable=True,
    paginate=20,
    deletable=True,
    editable=True,
    details=True,
    selectable=None,
    create=True,
    csv=True,
    links=None,
    links_in_grid=True,
    upload='<default>',
    args=[],
    user_signature=True,
    maxtextlengths={},
    maxtextlength=20,
    onvalidation=None,
    oncreate=None,
    onupdate=None,
    ondelete=None,
    sorter_icons=(XML('↑'), XML('↓')),
    ui = 'web2py',
    showbuttontext=True,
    _class="web2py_grid",
    formname='web2py_grid',
    search_widget='default',
    ignore_rw = False,
    formstyle = 'table3cols',
    exportclasses = None,
    formargs={},
    createargs={},
    editargs={},
    viewargs={},
    buttons_placement = 'right',
    links_placement = 'right'
    )

...
JoeNite: below => see SQLFORM
    http://web2py.com/books/default/chapter/29/07/forms-and-validators#SQLFORM
        http://web2py.com/books/default/chapter/29/07/forms-and-validators#SQLFORM-and-insert-update-delete
            google: SQLFORM for select
                https://groups.google.com/forum/#!topic/web2py/VKvw3Mn-mNQ


Because the edit/create form is an SQLFORM which extends FORM, these callbacks are essentially used in the same way as documented in the sections for FORM and SQLFORM.

Here is skeleton code:

def myonvalidation(form):
    print "In onvalidation callback"
    print form.vars
    form.errors= True  #this prevents the submission from completing

    #...or to add messages to specific elements on the form
    form.errors.first_name = "Do not name your child after prominent deities" 
    form.errors.last_name = "Last names must start with a letter"
    response.flash = "I don't like your submission" 

def myoncreate(form):
    print 'create!'
    print form.vars

def myonupdate(form):
    print 'update!'
    print form.vars

def myondelete(table, id):
    print 'delete!'
    print table, id

onupdate and oncreate are the same callbacks available to SQLFORM.process()    
'''    

Scrape HTML Files with lxml

GREAT lxml example links

HTML Node vs Element

W3C HTML Nodes may be:

  • Document — Element (maximum of one), ProcessingInstruction, Comment, DocumentType
  • DocumentFragment — Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
  • DocumentType — no children
  • EntityReference — Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
  • Element — Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference
  • Attr — Text, EntityReference
  • ProcessingInstruction — no children
  • Comment — no children
  • Text — no children
  • CDATASection — no children
  • Entity — Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
  • Notation — no children # My Scrape HTML File Example

Background

This, http://joecodeswell.org/examples/dlwebfiles/index.html, is the URL we will be scraping using lmxl, to find files to download, and using urllib to download them. Here is what the URL content looks like.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=windows-1252">
    <title>dlwebfiles</title>
  </head>
  <body>
    <h1>Index of Joe Codeswell examples - dlwebfiles</h1>
    <ul>
      <li><a href="http://joecodeswell.org/examples/dlwebfiles/aveverum.mid">aveverum.mid</a></li>
      <li><a href="http://joecodeswell.org/examples/dlwebfiles/carol.mid">carol.mid</a></li>
      <li><a href="http://joecodeswell.org/examples/dlwebfiles/steiner.mid">steiner.mid</a></li>
    </ul>
  </body>
</html>

Step-1

Create a folder structure on your local machine == “example_folder/mid".

Step-2

Put the following Python code into a file in example_folder, naming it “retrieveMidis.py“.

# -*- coding: UTF-8 -*-
# retrieveMidis.py

import os, lxml.html, urllib

inScrapeUrl = 'http://joecodeswell.org/examples/dlwebfiles/index.html'
outDataFolderPath = os.path.join('mid')

# parse the html
htmltree = lxml.html.parse(inScrapeUrl)

# retrieve the midi files to the ./mid dir
theLiList = htmltree.xpath('/html/body/ul/li')  
opener = urllib.URLopener()
for li in theLiList:
    # see http://www.w3schools.com/xpath/xpath_syntax.asp
    theHref = li.xpath('a')[0].attrib.get('href')
    theBasename = os.path.basename(theHref)
    theExtension = os.path.splitext(theBasename)[1]
    if len(theBasename) != 0:
        print "theHref = %s"%(theHref)
        print "theBasename = %s"%(theBasename)
        print "len(theBasename) = %s"%(len(theBasename))
        print "theExtension = %s"%(theExtension)
        print "os.path.join(outDataFolderPath,theBasenme) = %s"%(os.path.join(outDataFolderPath,theBasename))
        print
        print
        opener.retrieve(theHref, os.path.join(outDataFolderPath,theBasename))

Step-3

Run retrieveMidis.py.

Here’s what the output looks like on Win XP.

>retrieveMidis.py
theHref = http://joecodeswell.org/examples/dlwebfiles/aveverum.mid
theBasename = aveverum.mid
len(theBasename) = 12
theExtension = .mid
os.path.join(outDataFolderPath,theBasenme) = midaveverum.mid


theHref = http://joecodeswell.org/examples/dlwebfiles/carol.mid
theBasename = carol.mid
len(theBasename) = 9
theExtension = .mid
os.path.join(outDataFolderPath,theBasenme) = midcarol.mid


theHref = http://joecodeswell.org/examples/dlwebfiles/steiner.mid
theBasename = steiner.mid
len(theBasename) = 11
theExtension = .mid
os.path.join(outDataFolderPath,theBasenme) = midsteiner.mid


KVLang Series – 4

KVLang Series – 4

← Previous              Next →

Vertical BoxLayout

Content:
– .kv file
– .py file
– screenshot of output

0004_verticalBoxLayout.kv

Just add the BoxLayout orientation: ‘vertical’ property. This arranges its contents in a vertical manner instead of the default ‘horizontal’.

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Input:'
    TextInput:
        text: 'Default Text'
    Button:
        text: 'Press Me'

0004_verticalBoxLayout.py

This is adapted from previous python file. Again we make minor changes to update the .kv filename and give a new window height.

  1. EDIT

    CHANGE: The OLD self.root = Builder.load_file(”) TO the NEW

  2. EDIT

    WAS: Config.set(‘graphics’, ‘height’, ’30’)

    NOW: Config.set(‘graphics’, ‘height’, ’90’)

''' 0004_verticalBoxLayout.py
Used to display 0004_verticalBoxLayout.kv - Again, no new concepts in here.
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config

Config.set('graphics', 'width',  '323')
Config.set('graphics', 'height', '90')

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0004_verticalBoxLayout.kv')
        return self.root

if __name__ == '__main__':
    MyApp().run()

0004_verticalBoxLayout ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 323
– height: 200

Alt 0004_verticalBoxLayout.png

KVLang Series – 3

KVLang Series – 3

← Previous              Next →

More Widgets in a BoxLayout

Content:
– .kv file
– .py file
– screenshot of output

0003_moreWidgets.kv

In the .kv file we add some more widgets under a BoxLayout.
If we added the widgets directly to the file, not being underneath our layout, it would be and ERROR because they would be considered root rules and “you can have one root rule, and any number of class or template rules.”
The BoxLayout has a default orientation: ‘horizontal’.

### 0003_moreWidgets.kv

BoxLayout:
    Label:
        text: 'Input:'
    TextInput:
        text: 'Default Text'
    Button:
        text: 'Press Me'

0003_moreWidgets.py

This is adapted from previous python file. We make minor changes to update the .kv filename and give a new window height.

  1. EDIT

    CHANGE: The OLD self.root = Builder.load_file(”) TO the NEW

  2. EDIT

    WAS: Config.set(‘graphics’, ‘height’, ‘200’)

    NOW: Config.set(‘graphics’, ‘height’, ’30’)

''' 0003_moreWidgets.py
Used to display 0003_moreWidgets.kv - No new concepts in here.
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config

Config.set('graphics', 'width',  '323')
Config.set('graphics', 'height', '30')

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0003_moreWidgets.kv')
        return self.root

if __name__ == '__main__':
    MyApp().run()

0003_moreWidgets ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 323
– height: 200

Alt 0003_moreWidgets.png

KVLang Series – 2

KVLang Series – 2

← Previous              Next →

Window Size – Hello World Label Widget

Content:
– .kv file
– .py file
– screenshot of output

0002_windowSize.kv

This is PRETTY MUCH the same as before. Unfortunately (from my perspective), we must alter the .py file to change the window size. If anyone knows a way to do this in a .kv file please post it to the comments. Thanks.

Label:
    text: 'A smaller hello, world.'

0002_windowSize.py

As I said earlier, Unfortunately (from my perspective), we must alter the .py file to change the window size. If anyone knows a way to do this in a .kv file please post it to the comments. Thanks.

This is adapted from 0001_helloWorld.py. Here are the changes:

  1. EDIT – Builder.load_file()

    WAS: self.root = Builder.load_file(‘0001_helloWorld.kv’)

    NOW: self.root = Builder.load_file(‘0002_windowSize.kv’)

  2. ADD – Window Sizing Info

    AFTER: from kivy.lang import Builder

    BEFORE: class MyApp(App):

    INSERT:

    from kivy.config import Config

    Config.set(‘graphics’, ‘width’, ‘323’)

    Config.set(‘graphics’, ‘height’, ‘200’)

''' 0002_windowSize.py
Demonstrates Window Sizing - kivy.config - Config.set('graphics',
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config

Config.set('graphics', 'width',  '323')
Config.set('graphics', 'height', '200')

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0002_windowSize.kv')
        return self.root

if __name__ == '__main__':
    MyApp().run()

0002_windowSize ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 323
– height: 200

Alt 0002_windowSize.png