smZIP: A Class for Creating ZIP Archives in Python

The Python LogoCreating ZIP archives in Python was overly complicated prior to this class: smZIP. Rather than importing zipfile and having to constantly reference docs.python.org, I came up with a much simpler solution. smZIP practically does all of the work; all you have to do is tell it what to archive.

 

How to Use smZIP

 

This class relies on smIO, my class for simple IO procedures. Make sure you’ve got a copy in your import directory.

 

First, you must import the class. The following code will import the smZIP class and create an object called z. Since the verbose switch was provided, all actions of smZIP will be outputted.

 


#!/usr/bin/python
from smZIP import *
z = smZip(verbose = True)

 

Creating an Archive

 

The following code will create a new archive called test.zip. If the archive already exists, it will be overwritten.

 


z.createZip('test.zip', overwrite = True)

 

Adding a File to the Archive

 

The following code with add the file test.txt from the directory /home/stephen to the archive.

 


z.addFile('/home/stephen/', 'test.txt')

 

Adding a Directory to the Archive

 

The following code will add the directory /home/stephen/ to the archive.

 


z.addDirectory('/home/stephen/')

 

You may also add all directories contained in the specified directory recrusively by providing the recrusive switch.

 


z.addDirectory('/home/stephen/', recrusive = True)

 

Adding a Comment to the Archive

 

The following code will add a comment string to the archive.

 


z.addComment('This is a comment!')

 

You may also add a comment file to the archive.

 


z.addComment('This is a comment!', 'comment.txt')

 

Closing the Archive

 

With the usage of Python’s __del__ function, you are not required to close the archive. It is, however, strongly suggested that you do so.

 


z.close()

 

Working with Existing Archives

 

With this class, you may also add files, comments and directories to existing archives. All that needs to change here is how you open the archive. By default, the createZip function will not overwrite a file.

 


z.createZip('test.zip', overwrite = False)

 

 

Download smZIP:

 

This class is available under no license. You may do with it whatever you please. Just keep in mind: stealing code is lame.

smIO: Simple File I/O Class for Python

The Python LogoThis class (smIO) makes file I/O practices in Python easier than ever before.  To delete, modify and/or create files and directories in Python is extremely simple with this class.

 

 

All you need to do is create the class object and you’re ready to go.

#!/usr/bin/python
from smIO import *
if __name__ == '__main__':
IO = smIO()

With this class, you’re able to use several useful file I/O easily.

 

Delete a specific file or directory


IO.rm('./test.file')
IO.rm('./test_directory')

 

Delete several files based on their extension


IO.rmByExt('log', './test_directory')

 

Delete a directory


IO.rmdir('./test_directory')

Note – this will also remove all files in the specified directory.

 

Create a directory


IO.mkdir('./test_directory')

 

List files in a specific directory


fl = IO.listDir('./test_directory')
for fn in fl:
print fn

 

List files of a specific file extension in a directory


fl = IO.listDirByExt('./test_directory', 'log')
for fn in fl:
print fn

 

Perform file/directory existence checks


if IO.exists('./test.file'):
print 'file exists'
else:
print 'file does not exist'

 

Get the full path name of a file


print IO.getFilePath('./test.file')

 

Get the directory of a specific file


print IO.getFileDir('./test.file')

 

Download the smIO Python class:

 

 

 

This class is not OS specific and will function appropriately on Linux, Windows and Mac. Any questions or comments, please let me know.

How To: Display Recent Published WordPress Posts

Display Recent Published WordPress PostsOn the footer of this website, you see a section entitled “Recent Posts”. In this section, you see the most recently published posts of mine. This is typical amongst WordPress blogs for many reasons (including but not limited to: SEO, user friendliness, aesthetics, …) but can cause several headaches if not done properly.

When putting this template together, I had no idea that the WordPress function wp_get_recent_posts() would return all posts, including scheduled (not yet published) posts. Since I didn’t know this, I used the function and continued on coding. Once I thought I was finished, I started blogging. I wrote a few entries and came up with concepts for future posts and scheduled them for a later date.

Next time I took a look at my page, I realized that my footer provided links to unavailable posts: posts which had not been finished and were marked as scheduled. Being quite confused, I consulted Google. Not having the appropriate answer for me, I started searching for the function wp_get_recent_posts() inside of WordPress core. I used the following grep command to locate where the function was hiding:


stephen@localhost:/.../public_html/wp-includes$ grep -rn "wp_get_recent_posts" ./*.php

… and was prompted with:


./class-wp-xmlrpc-server.php:1811: $posts_list = wp_get_recent_posts( $query );
./class-wp-xmlrpc-server.php:2807: $posts_list = wp_get_recent_posts( $query );
./class-wp-xmlrpc-server.php:3048: $posts_list = wp_get_recent_posts( $query );
./post.php:2289:function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) {

I opened the file post.php, scrolled down to line 2289 and noticed these lines of PHP code:


// Set default arguments
$defaults = array(
'numberposts' => 10,
'offset' => 0,
'category' => 0,
'orderby' => 'post_date',
'order' => 'DESC',
'include' => '',
'exclude' => '',
'meta_key' => '',
'meta_value' =>'',
'post_type' => 'post',
'post_status' => 'draft, publish, future, pending, private',
'suppress_filters' => true
);

The default arguments being set request any post with the status of draft, publish, future, pending and private. Since I don’t want my readers to see drafts, future or pending posts, this is obviously not what I want.

I thought that I could make this an extremely simple fix and just remove the unwanted post statuses and call it a day, but this would only be a temporary solution. The next WordPress update would overwrite this file and I would have to re-solve a problem which I had already tackled. Instead, I created my own custom function and placed it in my functions.php file in my theme directory.

 

Creating the New Function

 

Since I know exactly what this function needs to do, I was able to keep it short and simple. All that is required is retrieving a specified number of published posts. My function looks like this:


function wp_get_recent_published_posts($num = 10){
global $wpdb;
$num = (int) $num;
if($num) $limit = "LIMIT $num";
$query = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' AND post_status IN ('publish', 'private') ORDER BY post_date DESC $limit";
$result = $wpdb->get_results($query, ARRAY_A);
return $result ? $result : array();
}

… and my problem has been solved!

Here’s a breakdown of what is happening:


global $wpdb;
$num = (int) $num;
if($num) $limit = "LIMIT $num";

This is just variable setup. I’m requiring the global class object wpdb, which holds functions for all database interactions done by WordPress. I am then forcing the variable num to become an integer, so that the function can be called two ways:


$foo = wp_get_recent_published_posts('3');
$bar = wp_get_recent_published_posts(3);

I then check if the variable num has a value greater than zero. If so, set a limit for the MySQL query.


$query = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' AND post_status IN ('publish', 'private') ORDER BY post_date DESC $limit";

Here I am creating the MySQL query. The only posts which will be selected are either published or private and have the post_type of post. The results are sorted by the date they were posted and if a limit was set, then only that many posts are returned.


$result = $wpdb->get_results($query, ARRAY_A);

Here, I’m requesting that the wpdb object queries MySQL and returns the requested posts.


return $result ? $result : array();

This is one of my favorite parts of PHP: shorthand IF-statements (don’t they look nice?). This line checks to see if the variable result has a value and if so, it returns it. If there is no variable in result, the function returns an empty array.

 

Using the New Function

 

Since we’ve created a new, usable function, we now need to put it into production. This function is used exactly the same way wp_get_recent_posts() is used, so nothing has to change. Below is how I’m utilizing my new function.


<h3>Recent Posts</h3>
<ul>
<?php

Open an unordered list and title it “Recent Posts” then open a PHP tag.


$recent_posts = wp_get_recent_published_posts(4);

Request four recently published posts from WordPress.


foreach($recent_posts as $post){

Begin to loop through each retrieved post.


$post_title = $post['post_title'];
if(strlen($post_title) > 30) $post_title = substr($post_title, 0, 25) . '...';

Retrieve the post’s title and if it is more than 30 characters, truncate it down to 25 characters and add an ellipsis.


$post_href = get_permalink($post['ID']);
echo "<li><a href = '$post_href'>$post_title</a></li>\n";
}

Get the URL of the post and display the post as a link item on the page. Close the loop.


?>
</ul>

Close the PHP tag and the unordered list.

 

Hopefully this WordPress tutorial was helpful to you. If you need any more assistance of a better understanding of any of the above, feel free to comment or contact me with your questions.

 

How to: Create a Simple External Links jQuery Plugin

jQuery External LinksDon’t be scared: creating your own jQuery plugin is simple.  We’re going to use my jQuery Plugin Skeleton and create a simple plugin which opens all external links in a new tab (or window).  This plugin is currently being used on this site.

 

Example link to Google

First Thing’s First (Step One)

 

Since I’ve already offered a simple jQuery plugin skeleton for you, we’re going to start with it.  I’ve chosen to name this plugin “externalLinks”, but you’re able to call it whatever you like.


(function($){
    $.fn.extend({
        // external links
        externalLinks: function(options){
            var defaults = { option : 'value' };
            var options = $.extend(defaults, options);
            return this.each(function(){
                var o = options;
            });
        }
    });
})(jQuery);

Download step1.js:

Step 2: Default Variables

 

Now that we’ve initialized jQuery and named our plugin, we need to set up our default variables.  I’m using the class name external, which will be applied to all external links.  This allows us to style the links with CSS later.  This also allows for user customization, but we’ll discuss this later too.


(function($){
    $.fn.extend({
        // external links
        externalLinks: function(options){
            var defaults = { className : 'external' };
            var options = $.extend(defaults, options);
            return this.each(function(){
                var o = options;
            });
        }
    });
})(jQuery);

Download step2.js:

Step 3: Filtering Through Links

 

We’ll deal with styling the external class later.  Let’s focus on our code for now.

We now need to find all appropriate links to apply this classname to.  We’ll do this with jQuery’s filter function.  We’ll examine the hostname of each anchor’s HREF and ensure that it is different from our own, and also verify that the anchor is not already associated with our specified classname.

Once we have found these anchors, we need to capture their click event.


(function($){
    $.fn.extend({
        // external links
        externalLinks: function(options){
            var defaults = { className : 'external' };
            var options = $.extend(defaults, options);
            return this.each(function(){
                var o = options;
                $(this).filter(function(){
                    return this.hostname && (this.hostname).split(":")[0] !== (location.hostname).split(":")[0] || $(this).hasClass(o.className);
                }).click(function(event){
                    // do stuff.
                });
            });
        }
    });
})(jQuery);

Download step3.js:

Step 4: More Specific Filtration

 

Though we’ve already found anchors which point to a hostname different than our own, we still need to limit them further.  We also need to supply the filter function with an end() statement.  Anchors which contain an image are not going to be given our previously specified classname.


(function($){
    $.fn.extend({
        // external links
        externalLinks: function(options){
            var defaults = { className : 'external' };
            var options = $.extend(defaults, options);
            return this.each(function(){
                var o = options;
                $(this).filter(function(){
                    return this.hostname && (this.hostname).split(":")[0] !== (location.hostname).split(":")[0] || $(this).hasClass(o.className);
                })
                .not(':has(img)')
                .addClass(o.className)
                .end()
                .click(function(event){
                    // do stuff.
                });
            });
        }
    });
})(jQuery);

Download step4.js:

Step 5: Finally Opening the Link

 

Now that we’ve limited the anchors to exactly what we want, we’re able to finally open the link.  This could be done multiple ways, but I’ve chosen to use JavaScript’s open() method.  We’re also going to call jQuery’s PreventDefault() function, just to prevent anything extra from happening.


(function($){
    $.fn.extend({
        // external links
        externalLinks: function(options){
            var defaults = { className : 'external' };
            var options = $.extend(defaults, options);
            return this.each(function(){
                var o = options;
                $(this).filter(function(){
                    return this.hostname && (this.hostname).split(":")[0] !== (location.hostname).split(":")[0] || $(this).hasClass(o.className);
                })
                .not(':has(img)')
                .addClass(o.className)
                .end()
                .click(function(event){
                    open(this.href);
                    event.preventDefault();
                });
            });
        }
    });
})(jQuery);

Download step5.js:

Step 6: Applying Style

 

In a CSS document (or in-line CSS) we need to style our selected classname.  I am adding an image to the anchor.


a.external {
    background-image: url('icon-external-link.png');
    background-position: right top;
    background-repeat: no-repeat;
    padding-right: 20px;
    zoom: 1; /* IE */
}

Download icon-external-link.png:

Step 7: Applying the Plugin to Your Web Page

 

This is our last step, as we’ve successfully created our plugin and styled the necessary classes.  Since it’s now completed and in working order, I’ve renamed it “jquery-externallinks.js”.  We now need to include it and the jQuery library into our web page.


<script src = "//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type = "text/javascript"></script>
<script src = "jquery-externallinks.js" type = "text/javascript"></script>

We also need to call our plugin, which is a simple one-liner.  We create a self-executing function and insert our plugin call into it.


<script type = "text/javascript">$
(function(){
    $('a').externalLinks();
});
</script>

Download entire package:

 

I hope you’ve learned something here, and if you require any more assistance, feel free to let me know via comments or my contact page.

jQuery Plugin Skeleton

jQuery Plugin SkeletonOver the years, I’ve developed a simple skeleton for jQuery plugins. When creating your own plugin, it’s nice to have a semi-strict format to follow. All of my plugins use this skeleton.


(function($){
    $.fn.extend({
        // plugin name
        pluginName: function(options){
            var defaults = {
                option : 'value'
            }

            var options = $.extend(defaults, options);

            return this.each(function(){
                var o = options;
            });

        }
    });
})(jQuery);

Download this file:

New HTML5 WordPress Theme

New HTML5 WordPress Theme

 

As stated in my first post, I’ve started producing a new HTML5 WordPress theme.

Thus far, I’ve customized and added to the Toolbox WordPress theme by Automatic.  With quite a bit of customization, I’ve created what you’re looking at now.

 

 

 

 

Over the next few weeks, I’ll be describing individual elements of this HTML5 WordPress theme, and providing a step-by-step tutorial of how to create your own.  Two topics which I’ll be covering in great detail are using jQuery plugins and HTML5 to create a custom WordPress theme and simple PHP hacks for better theme performance.

 

Installation of WordPress via SSH

Brief tutorial of how to install WordPress via SSH

After having trouble with Fantastico on my HostGator account, I decided to install a fresh copy of WordPress via SSH.

 

I’ve been a long-time fan of HostGator’s hosting services, which is where this site is hosted.  HostGator (amongst several other hosting companies) offer the usage of Fantastico.  Fantastico allows for simple (practically) single-click installation of web-applications (CMS, blogging platforms, image galleries, FAQs, etc.) to a web site.

Just for simplicity, I navigated to the Fantastico Delux icon and attempted to install WordPress.  Everything went smoothly, according to Fantastico.  After the installation, I attempted to login to my WordPress admin panel.  This is where everything went awry.  I was unable to login with my username and password, but was never prompted with an error; the page (/wp-login.php) was just refreshed.  Strange, right?  After several tries, I consoulted Google.  I read somewhere that I needed to remove files left behind by fantasico (fantversion.php, fantfilelist.txt, *fant*.*), but this did nothing.

Finally, I decided that correcting this issue was more complicated than necessary, and installed WordPress manually via SSH.  This is how.

 

First, I opened up my terminal and opened an SSH session.

stephen@localhost:~$ ssh -p 2222 username@domain.com

Note – the “p” switch specifies port.  HostGator only allows SSH access on port 2222.  The default SSH port is 22.

Next, I navigated to the directory where I wanted to install WordPress.

cd /home/stephen/public_html/

While in this directory, I had to download and uncompress the latest version of WordPress.

wget http://wordpress.org/latest.tar.gz
tar xfz latest.tar.gz

Note – The latest.tar.gz archive will extract to ./wordpress/.

Now that the files have been downloaded and extracted from the archive, it’s time to put them in place.  I changed directory to ./wordpress/ and copied over all of the files.

cd ./wordpress
cp -rpf * ../

Note – the “r” switch indicates recrusive (copy directories recursively), the “p” switch indicates preserve (preserve the specified attributes) and the “f” switch indicates force (if an existing destination file cannot be opened, remove it and try again).

I then navigated back to the previous directory and verified that the files had copied correctly.

cd ..
ls

Since the files had been copied into place, the ./wordpress directory and all of its contents were no longer required.  I removed the files and the directory.

rm -rf ./wordpress

Note – Same switches as before: “r” for recrusive and “f” for force.

Now that the files are in place and ready, we have to get MySQL ready.

 

After logging into MySQL
mysql -uUSERNAME -pPASSWORD

I originally tried the following few MySQL queries…

CREATE DATABASE stephen_wordpress_database;
CREATE USER 'stephen_wp_user'@'localhost' IDENTIFIED BY 'password';
GRANT USAGE ON *.* TO 'stephen_wp_user'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON stephen_wordpress_database.* TO 'stephen_wp_user'@'localhost';

But was unsussessful. For an unknown reason (reference or reason?), I am not able to create a MySQL user. Because of this, I had to set up MySQL via the cPanel. HostGator support has an article of how to do so avaliable here.

Note – I would highly suggest using HostGator’s random password generator for your MySQL user.

Once MySQL was ready, I needed to setup WordPress.

 

First, I had to rename the sample WordPress configuration file like so:

mv wp-config-sample.php wp-config.php

Then, using Vim (you may use Vi, Vim, Nano, … HostGator has a lot of editors installed by default), I edited the newly created wp-config.php file.

vim ./wp-config.php

Once the wp-config.php file is opened, I switched the editor into INSERT mode and found the line defining DB_NAME.  I entered my MySQL database name like so…

/** The name of the database for WordPress */
define('DB_NAME', 'stephen_wordpress_database');

I then edited the DB_USER line, adding the MySQL username.

/** MySQL database username */
define('DB_USER', 'stephen_wp_user');

Lastly, I entered the randomly generated password for my MySQL user at the DB_PASSWORD line.

/** MySQL database password */
define('DB_PASSWORD', 'password');

I did not have to edit any other lines (DB_HOST, DB_CHARSET, DB_COLLATE, etc.), as the defaults are suitable for my needs.

 

Once the configuration file was properly edited, I let WordPress do the rest.  I went to the URL where I originally downloaded and extracted WordPress and followed the instructions provided.

Now that WordPress has been installed, I’ve started creating my own WordPress theme, where I’ll be using HTML5, lots of CSS hacks and of course, some jQuery.