28 septembre 2010

Using multiple inheritance for Python mocks

Today, I needed to mock just one function from a class instance.

I used multiple inheritance to achieve that like so:



The ProdEngineMock class inherits everything from the ProdEngine class, except the mocked function.

Nice and elegant!

25 septembre 2010

Convert a sql_ascii Postgres database to a UTF8 one

pg_dump -f your_db.dmp your_db

iconv -f ISO8859-1 -t UTF-8 your_db.dmp > utf.dmp

psql your_utf_db < utf.dmp

Note that Rails was used to input the data into my old sql_ascii database, so the encoding was consistent. You might not be so lucky...

Identify large tables on Postgres

To quickly know which of your Postgres tables are the largest:

select relname, reltuples from pg_class order by reltuples desc;

reltuples are the number of rows, so this command will show your largest tables first.

Rails validates_length_of and byte encoding

Why you should NEVER create a Postgres database with the default sql_ascii encoding set to use with Rails


Ruby prior to 1.9 considers strings as bytes, and that can cause some maddening issues. In my experience, all encoding issues are maddening...

Anyway, I had a validates_length_of like so:



I got a problematic lead from a customer (that included special Word characters that were multi-bytes), put them in a test and started a debug session:



What???

After some digging, Rails, in order to consider characters and not bytes, uses split(//).size instead of size directly. Split(//) is the default tokenizer of validates_length_of and it can be changed as an option passed to the validates method. See http://railspikes.com/2009/7/20/validates_length_of-gotcha for more details.

My original problem, though, was that the lead was 499 characters, but 517 bytes and my Postgres database was encoded with the default sql_ascii encoding set.

Therefore, my constraint on Postgres column lead "character varying(500)" translated to 500 bytes maximum...

Conclusion: never ever create a Postgres database with the default sql_ascii encoding set to use with Rails. Always use the utf8 encoding set. Even if you deal only with English: special characters exist in all languages...

15 septembre 2010

Samba to follow symbolic links on Ubuntu

Add to /etc/samba/smb.conf:
follow symlinks = yes
wide symlinks = yes
unix extensions = no
And reload the Samba configuration:
sudo service smbd reload

Mount a new hard drive on Ubuntu

Check that the disk is available:
sudo lshw -C disk
(this will give you a list of available disks, find the one you want to mount and copy its logical name. For instance, the logical name could be: /dev/sdb)

Partition the disk on the command line:
sudo fdisk /dev/sdb 

Create a new partition: n
Select a primary partition: p
Select the first partition: 1
Write the new partition: w

Format the new disk:
sudo mkfs -t ext3 /dev/sdb1

Create a new mount point:
sudo mkdir /media/extradrive

Edit /etc/fstab (sudo vi /etc/fstab) and add a line:

/dev/sdb1 /media/extradrive      ext3    defaults        0       2

Reload the mounts:
sudo mount -a

Change the ownership and rights of the new drive:
sudo chown -R USERNAME:USERNAME /media/extradrive
sudo chmod 755 /media/extradrive

Where are my packages?

A good trick to know where your Python packages are located:

python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

Change environment variables for Apache on Mac OS X

In order to get a new environment variable accessible to Apache on Mac OS X (10.6), you need to edit the /etc/launchd.conf file and add:

setenv MY_VAR /my/value/here

Create an Ubuntu VM with Sun's VirtualBox (with Oracle XE)

sudo mkdir /mnt/cdrom
sudo mount /dev/cdrom /mnt/cdrom
cd /mnt/cdrom/
sudo ./VBoxLinuxAdditions-x86.run

sudo mkdir /mnt/downloads
sudo mount.vboxsf Downloads /mnt/downloads/

sudo cp /mnt/downloads/oracle-xe-universal_10.2.0.1-1.0_i386.deb

sudo apt-get install bc
sudo apt-get install libaio1

#expand swap:
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
sudo mkswap /swapfile
sudo vi /etc/fstab and add at the bottom:
/swapfile none swap sw 0 0

dpkg -i oracle-xe-universal_10.2.0.1-1.0_i386.deb

sudo /etc/init.d/oracle-xe configure

Export from another machine:
exp full=y file=shi.dump
(you are prompted for username/pwd, use sys as sysdba)

Increase the number of processes available to Oracle:
ALTER SYSTEM SET PROCESSES=150 SCOPE=SPFILE;

MAKE SURE that:

* SID in tnsnames.ora is the same as ORACLE_SID in environment variables (it is case sensitive!)

* ORACLE_HOME doe NOT end with a /

in Oracle:
CREATE USER reb identified by reb;
GRANT CREATE SESSION TO reb;
GRANT UNLIMITED TABLESPACE TO reb;


imp fromuser=reb commit=y ignore=y file=shi.dump

Same for users: SEL1, SEL2, SEL3, IDCX, LEB, STATIC, RMSAUTO, RMSMAN

For RAD, users are: RMSUSER, RMSMAN, RMSAUTO, IDCX, NMS, NMSGSYS

Grant special privileges to users that need to create tables and sequences:
GRANT CREATE TABLE TO nmsgsys;
GRANT CREATE SEQUENCE TO nmsgsys;
GRANT CREATE TABLE TO nms;
GRANT CREATE SEQUENCE TO nms;

Create user NMS_USER (same syntax as above) and grant privileges:

sqlplus sys/sysdba@ctbtoenv/xe as sysdba @grant_privileges NMS NMSUSER
sqlplus sys/sysdba@ctbtoenv/xe as sysdba @grant_sequence_privileges NMS NMSUSER
sqlplus sys/sysdba@ctbtoenv/xe as sysdba @grant_privileges NMSGSYS NMSUSER
sqlplus sys/sysdba@ctbtoenv/xe as sysdba @grant_sequence_privileges NMSGSYS NMSUSER

sudo adduser nmsuser (pwd: nmsuser)