AI slop ?

It has recently been a passionate subject, and I’ve seen quite a few people (colleagues, community members) dismissing anything with “ai” in it as “slop”. Personally, I could perhaps understand that argument a year or so ago, but from more recent trials, the agents have progressed far enough that they’ve become very good (although they seem to still struggle a little if you’re asking them to use new APIs/library versions etc). Continue reading “AI slop ?”

Animal Licensing – Paws On the Doors

Last Monday saw the launch of Paws On the Doors – Animal Licensing – which aims to have animal licensing data for England – providing the public with a single place to lookup animal licensing inspections / data.

Under the hood it’s using PHP/Laravel, TypeSense and some magic fairy dust.

It’s kind of related to ScoresOnTheDoors – UK Food Hygiene Ratings – but with a refreshed code base (we felt it was time to move on from a code base that’s probably 20 something years old and start from a cleaner slate without legacy baggage).

ssh signed git commits

git config –global gpg.format ssh
git config –global user.signingkey ~/.ssh/id_ed25519.pub
git config –global commit.gpgsign true

Hopefully that’ll result in my github commits being signed…. and when I forget how to do it …

docker proxy image download

Docker doesn’t like me for some reason, and I often get really bad download speeds from my home IP address.

One crude fix, is use an external server I can access as a SOCKS proxy.
To do so, edit / create /etc/systemd/system/docker.service.d/http-proxy.conf and put in it :

[Service]
Environment="HTTP_PROXY=socks5://localhost:8888"

Then, restart/reload systemd ( systemctl daemon-reload ; service docker restart )

Then, setup your socks tunnel using some remote server you have SSH access on –

ssh -D 8888 david@some.remote.server

Hopefully now when you do a ‘docker-compose up‘ it won’t take forever.

A crude way of speed testing it, is to try running this bash snippet :

token=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/mysql:pull" | jq -r .token)

curl -v https://registry-1.docker.io/v2/library/mysql/blobs/sha256:2a72cbf407d67c7a7a76dd48e432091678e297140dce050ad5eccad918a9f8d6 -H "Authorization: Bearer $token" -L > /dev/null

Mockery (test doubles/mocking dependencies)

[This is a relatively old post I think I forgot to publish….]

Previously, I’d only used PHPUnit’s mock implementation; however lately I’ve been exposed to Mockery.

While they both achieve broadly the same result (at least from my point of view), here’s an example of how to mock dependencies with Mockery.

Class to test:

class TestMe {
    private $db;
    public function __construct(PDO $db) {
        $this->db = $db;
    }

    public function doesSomethingImportant(array $data) : bool {
        $stmt = $this->db->prepare("UPDATE my_table SET field2 = :field2 WHERE field1 = :field1");
        return $stmt->execute(['field1' => $data['field1'], 'field2' => $data['field2']);

    }
}

And to test ….

....
use Mockery as m;
class MyTest extends \PHPUnit\Framework\TestCase {
    public function tearDown() {
        m::close();
        parent::tearDown();
   }
    public function testDoesSomethingImpotant() {
        $fakePdo = m::mock(\PDO::class);
        $stmt = m::mock(\PDOStatement::class);
        $stmt
           ->shouldReceive('execute')
           ->withArgs(['field1' => 'hello', 'field2' => 'world'])
           ->once()
           ->andReturn(true);
        $fakePdo
           ->shouldReceive('prepare')
           ->withArgs(['UPDATE my table SET field2 = :field2 WHERE field1 = :field1'])
           ->once()
           ->andReturn($stmt);

        $testClass = new TestMe($fakePdo);
        $this->assertTrue(
            $testClass->updateSomething(['field1' => 'hello', 'field2' => 'world']);
    }
}

So that’s all well and good, and with a little imagination you can see how a method that does some calculation could be tested to ensure it does the calculation correctly and performs the appropriate database query. It obviously requires you inject all dependencies in to the class (else you can’t pass in the appropriate mocks!)

While this test is isolated from the underlying database, it doesn’t ensure you code will work – what if someone’s changed the database schema – your test will still (incorrectly) pass …

You can also create ‘fake’ errors throughout your code which might help give you a higher code coverage score 🙂

$pdo = m::mock(PDO::class);

$pdo->shouldReceive('prepare')
    ->withArgs(['bad sql'])
    ->andThrow(PDOException::class);

$pdo->shouldReceive('prepare')
    ->withArgs(['whatever good sql'])
    ->once()
    ->andReturn($stmt);

$pdo->shouldReceive('prepare')
    ->withArgs(['more good sql'])
    ->once()
    ->andReturn($stmt);
....

vagrant commands for the lazy and forgetful

Vagrant commands :

  • vagrant up  – aka “clocking on at work, time to boot up the VM”
  • vagrant status – aka “did I leave that VM running last night?”
  • vagrant halt – aka “time to go home or change project”
  • vagrant destroy – aka “VM is broken; kill it with fire and deploy a virgin VM to start again”
  • vagrant package default –output /path/to/output/file.box – aka “I like this VM, I think I’ll keep a copy around somewhere for future purposes”
  • vagrant init – aka “Get this project started …”

 

Obviously requires you have a reasonably good ‘Vagrantfile’ to start with…..

Checking PHP code for compatibility issues

One project I occassionally hack on is Xerte Toolkits.

Yesterday on the mailing list it came up that someone was trying to use XOT with PHP4.

After getting over some initial shock that people still use PHP4 (it was end-of-lifed in August 2008) I wondered how easy it would be to check the status of a code base to find how incompatible with PHP4 it now is.

My initial thought was to find a list of functions which had been added with PHP5 and then just grep the code for them, but it turns out there is a much nicer approach – PHP_CompatInfo

Installation was fairly straight forward – like :

pear channel-discover bartlett.laurent-laville.org
pear install bartlett/PHP_CompatInfo

Annoyingly the documentation seemed well hidden – but once I found it (http://php5.laurent-laville.org/compatinfo/manual/2.3/en/index.html#_documentation) it was pretty easy to use, and the ‘phpci’ command did all I needed –

Examples :

1. List global variables in use :

$ phpci print --reference PHP5 --report global -R . 
436 / 436 [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++>] 100.00%
BASE: /home/david/src/XOT/trunk

-------------------------------------------------------------------------------
PHP COMPAT INFO GLOBAL SUMMARY
-------------------------------------------------------------------------------
  GLOBAL                                                  VERSION         COUNT
-------------------------------------------------------------------------------
                                        $_GET             4.1.0               1
  data                                  $_GET             4.1.0               2
  debug                                 $_GET             4.1.0               2
  export                                $_GET             4.1.0               2
  file                                  $_GET             4.1.0               1
  firstname                             $_GET             4.1.0               1
....

2. Find all PHP5 functions in use :

$ phpci print  --report function -R . | grep 5.
436 / 436 [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++>] 100.00%
  spl_autoload_register                 SPL               5.1.2               1
  simplexml_load_file                   SimpleXML         5.0.0               1
  iconv_set_encoding                    iconv             4.0.5               1
  iconv_strlen                          iconv             5.0.0              10
  iconv_strpos                          iconv             5.0.0              38
  iconv_strrpos                         iconv             5.0.0               3
  iconv_substr                          iconv             5.0.0              33
  dirname                               standard          4.0.0              53
  fclose                                standard          4.0.0              51
  file_put_contents                     standard          5.0.0               6
  fopen                                 standard          4.0.0              55
  fread                                 standard          4.0.0              57
  fwrite                                standard          4.0.0              50
  htmlentities                          standard          5.2.3               1
  md5                                   standard          4.0.0               1
  scandir                               standard          5.0.0               1
  str_split                             standard          5.0.0               3
REQUIRED PHP 5.2.3 (MIN) 
Time: 0 seconds, Memory: 28.25Mb

and finally,

3. Class usage :

$ phpci print  --report class -R . | grep 5.
436 / 436 [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++>] 100.00%
  Exception                             SPL               5.1.0               1
  InvalidArgumentException              SPL               5.1.0               2
REQUIRED PHP 5.1.0 (MIN)

4. All class usage :

i.e. without me grep’ping the results.

$ phpci print  --report class -R . 
436 / 436 [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++>] 100.00%
BASE: /home/david/src/XOT/trunk

-------------------------------------------------------------------------------
PHP COMPAT INFO CLASS SUMMARY
-------------------------------------------------------------------------------
  CLASS                                 EXTENSION         VERSION         COUNT
-------------------------------------------------------------------------------
  Exception                             SPL               5.1.0               1
  InvalidArgumentException              SPL               5.1.0               2
  PHP_CompatInfo                                          4.0.0               1
  Snoopy                                                  4.0.0               2
  StdClass                                                4.0.0               2
  Xerte_Authentication_Abstract                           4.0.0               6
  Xerte_Authentication_Factory                            4.0.0               4
  Xerte_Authentication_Guest                              4.0.0               1
  Xerte_Authentication_Ldap                               4.0.0               1
  Xerte_Authentication_Moodle                             4.0.0               1
  Xerte_Authentication_Static                             4.0.0               1
  Xerte_Authetication_Db                                  4.0.0               1
  Zend_Exception                                          4.0.0               2
  Zend_Locale                                             4.0.0               7
  Zend_Locale_Data                                        4.0.0              19
  Zend_Locale_Data_Translation                            4.0.0               6
  Zend_Locale_Exception                                   4.0.0              28
  Zend_Locale_Format                                      4.0.0               3
  Zend_Locale_Math                                        4.0.0              14
  Zend_Locale_Math_Exception                              4.0.0               9
  Zend_Locale_Math_PhpMath                                4.0.0              11
  archive                                                 4.0.0               3
  bzip_file                                               4.0.0               1
  dUnzip2                                                 4.0.0               3
  gzip_file                                               4.0.0               1
  tar_file                                                4.0.0               3
  toolkits_session_handler                                4.0.0               1
  zip_file                                                4.0.0               2
-------------------------------------------------------------------------------
A TOTAL OF 28 CLASS(S) WERE FOUND
REQUIRED PHP 5.1.0 (MIN) 
-------------------------------------------------------------------------------
Time: 0 seconds, Memory: 27.50Mb
-------------------------------------------------------------------------------

Which answers my question(s) and so on.