Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-wxpython-28-advanced-building-blocks-user-interface
Packt
30 Dec 2010
10 min read
Save for later

wxPython 2.8: Advanced Building Blocks of a User Interface

Packt
30 Dec 2010
10 min read
Displaying collections of data and managing complex window layouts are a task that most UI developers will be faced with at some point. wxPython provides a number of components to help developers meet the requirements of these more demanding interfaces. As the amount of controls and data that an application is required to display in its user interface increases, so does the task of efficiently managing available screen real estate. To fit this information into the available space requires the use of some more advanced controls and containers; so let's dive in and begin our exploration of some of the more advanced controls that wxPython has to offer. Listing data with a ListCtrl The ListCtrl is a versatile control for displaying collections of text and/or images. The control supports many different display formats, although typically its most often-used display mode is the report mode. Report mode has a visual representation that is very similar to a grid or spreadsheet in that it can have multiple rows and columns with column headings. This recipe shows how to populate and retrieve data from a ListCtrl that was created in report mode. How to do it... The ListCtrl takes a little more set up than most basic controls, so we will start by creating a subclass that sets up the columns that we wish to have in the control: class MyListCtrl(wx.ListCtrl): def __init__(self, parent): super(MyListCtrl, self).__init__(parent, style=wx.LC_REPORT) # Add three columns to the list self.InsertColumn(0, "Column 1") self.InsertColumn(1, "Column 2") self.InsertColumn(2, "Column 3") def PopulateList(self, data): """Populate the list with the set of data. Data should be a list of tuples that have a value for each column in the list. [('hello', 'list', 'control'),] """ for item in data: self.Append(item) Next we will create an instance of our ListCtrl and put it on a Panel, and then use our PopulateList method to put some sample data into the control: class MyPanel(wx.Panel): def __init__(self, parent): super(MyPanel, self).__init__(parent) # Attributes self.lst = MyListCtrl(self) # Setup data = [ ("row %d" % x, "value %d" % x, "data %d" % x) for x in range(10) ] self.lst.PopulateList(data) # Layout sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.lst, 1, wx.EXPAND) self.SetSizer(sizer) # Event Handlers self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) def OnItemSelected(self, event): selected_row = event.GetIndex() val = list() for column in range(3): item = self.lst.GetItem(selected_row, column) val.append(item.GetText()) # Show what was selected in the frames status bar frame = self.GetTopLevelParent() frame.PushStatusText(",".join(val)) How it works... Usually there tends to be a fair amount of set up with the ListCtrl, and due to this it is good to encapsulate the usage of the control in a specialized subclass instead of using it directly. We kept things pretty basic here in our ListCtrl class. We just used the InsertColumn method to set our list up with three columns. Then the PopulateList method was added for convenience, to allow the population of the ListCtrl from a Python list of data. It simply wraps the Append method of ListCtrl, which just takes an iterable that has a string for each column in the list. The MyPanel class is there to show how to use the ListCtrl class that we created. First we populate it with some data by generating a list of tuples and calling our PopulateList method. To show how to retrieve data from the list, we created an event handler for EVT_LIST_ITEM_SELECTED which will be fired each time a new selection is made in the control. In order to retrieve a value from a ListCtrl, you need to know the row and column index of the cell that you wish to retrieve the data from, and then call GetItem with the row and column to get the ListItem object that represents that cell. Then the string value of the cell can be retrieved by calling the GetText method of ListItem. There's more... Depending on the style flags that are used to create a ListCtrl, it will behave in many different possible ways. Because of this, it is important to know some of the different style flags that can be used to create a ListCtr.   Style flags Description LC_LIST In List mode, the control will calculate the columns automatically, so there is no need to call InsertColumn. It can be used to display strings and, optionally, small icons LC_REPORT Single or multicolumn report view that can be shown with or without headers LC_ICON Large icon view that can optionally have labels LC_SMALL_ICON Small icon view that can optionally have labels LC_EDIT_LABELS Allow the item labels to be editable by users LC_NO_HEADER Hide the column headers (report mode) LC_SORT_ASCENDING Sort items in ascending order (must provide a SortItems callback method) LC_SORT_DESCENDING Sort items in descending order (must provide a SortItems callback method) LC_HRULE Draw a horizontal line between rows (report mode) LC_VRULE Draw a vertical line between columns (report mode) LC_SINGLE_SEL Only allow a single item to be selected at a time (Default is to allow for multiple selections) LC_VIRTUAL Fetch items to display in the list on demand (report mode) Virtual Mode When a ListCtrl is created in virtual mode (using the LC_VIRTUAL style flag), it does not store the data internally; instead it will instead ask for the data from a datasource when it needs to display it. This mode is useful when you have a very large set of data where preloading it in the control would present performance issues. To use a ListCtrl in virtual mode, you must call SetItemCount to tell the control how many rows of data there are, and override the OnGetItemText method to return the text for the ListItem when the control asks for it. Browsing files with the CustomTreeCtrl A TreeCtrl is a way of displaying hierarchical data in a user interface. The CustomTreeCtrl is a fully owner-drawn TreeCtrl that looks and functions much the same way as the default TreeCtrl, but that offers a number of additional features and customizability that the default native control cannot. This recipe shows how to make a custom file browser class by using the CustomTreeCtrl. How to do it... To create this custom FileBrowser control, we will use its constructor to set up the images to use for the folders and files in the tree: import os import wx import wx.lib.customtreectrl as customtree class FileBrowser(customtree.CustomTreeCtrl): FOLDER, ERROR, FILE = range(3) def __init__(self, parent, rootdir, *args, **kwargs): super(FileBrowser, self).__init__(parent, *args, **kwargs) assert os.path.exists(rootdir), "Invalid Root Directory!" assert os.path.isdir(rootdir), "rootdir must be a Directory!" # Attributes self._il = wx.ImageList(16, 16) self._root = rootdir self._rnode = None # Setup for art in (wx.ART_FOLDER, wx.ART_ERROR, wx.ART_NORMAL_FILE): bmp = wx.ArtProvider.GetBitmap(art, size=(16,16)) self._il.Add(bmp) self.SetImageList(self._il) self._rnode = self.AddRoot(os.path.basename(rootdir), image=FileBrowser.FOLDER, data=self._root) self.SetItemHasChildren(self._rnode, True) # use Windows-Vista-style selections self.EnableSelectionVista(True) # Event Handlers self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnExpanding) self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnCollapsed) def _GetFiles(self, path): try: files = [fname for fname in os.listdir(path) if fname not in ('.', '..')] except OSError: files = None return files The following two event handlers are used to update which files are displayed when a node is expanded or collapsed in the tree: def OnCollapsed(self, event): item = event.GetItem() self.DeleteChildren(item) def OnExpanding(self, event): item = event.GetItem() path = self.GetPyData(item) files = self._GetFiles(path) # Handle Access Errors if files is None: self.SetItemImage(item, FileBrowser.ERROR) self.SetItemHasChildren(item, False) return for fname in files: fullpath = os.path.join(path, fname) if os.path.isdir(fullpath): self.AppendDir(item, fullpath) else: self.AppendFile(item, fullpath) The following methods are added as an API for working with the control to add items and retrieve their on-disk paths: def AppendDir(self, item, path): """Add a directory node""" assert os.path.isdir(path), "Not a valid directory!" name = os.path.basename(path) nitem = self.AppendItem(item, name, image=FileBrowser.FOLDER, data=path) self.SetItemHasChildren(nitem, True) def AppendFile(self, item, path): """Add a file to a node""" assert os.path.isfile(path), "Not a valid file!" name = os.path.basename(path) self.AppendItem(item, name, image=FileBrowser.FILE, data=path) def GetSelectedPath(self): """Get the selected path""" sel = self.GetSelection() path = self.GetItemPyData(sel) return path def GetSelectedPaths(self): """Get a list of selected paths""" sels = self.GetSelections() paths = [self.GetItemPyData(sel) for sel in sels ] return paths How it works... With just a few lines of code here we have created a pretty useful little widget for displaying and working with the file system. Let's take a quick look at how it works. In the classes constructor, we added a root node with the control's AddRoot method. A root node is a top-level node that has no other parent nodes above it. The first argument is the text that will be shown, the image argument specifies the default image for the TreeItem, and the data argument specifies any type of data associated with the item—in this case we are setting a string for the items path. We then called SetItemHasChildren for the item so that it will get a button next to it to allow it to be expanded. The last thing that we did in the constructor was to Bind the control to two events so that we can update the tree when one of its nodes is being expanded or collapsed. Immediately before the node is going to be expanded our handler for EVT_TREE_ITEM_ EXPANDING will be called. It is here where we find all the files and folders under a directory node, and then add them as children of that node by calling AppendItem, which works just like AddRoot but is used to add items to already-existing nodes in the tree. Conversely when a node in the tree is going to be collapsed, our EVT_TREE_ITEM_COLLAPED event handler will be called. Here we simply call DeleteChildren in order to remove the children items from the node so that we can update them more easily the next time that the node is expanded. Otherwise, we would have to find what was different the next time it was expanded, and then remove the items that have been deleted and insert new items that may have been added to the directory. The last two items in our class are for getting the file paths of the selected items, which—since we store the file path in each node—is simply just a matter of getting the data from each of the currently-selected TreeItems with a call to GetPyData. There's more... Most of what we did in this recipe could actually also be replicated with the standard TreeCtrl. The difference is in the amount of extra customizability that the CustomTreeCtrl provides. Since it is a fully owner-drawn control, nearly all of the visible attributes of it can be customized. Following is a list of some of the functions that can be used to customize its appearance:
Read more
  • 0
  • 0
  • 4076

article-image-drupal-faqs
Packt
30 Dec 2010
5 min read
Save for later

Drupal FAQs

Packt
30 Dec 2010
5 min read
  Drupal 7 First Look Learn the new features of Drupal 7, how they work and how they will impact you Get to grips with all of the new features in Drupal 7 Upgrade your Drupal 6 site, themes, and modules to Drupal 7 Explore the new Drupal 7 administration interface and map your Drupal 6 administration interface to the new Drupal 7 structure Complete coverage of the DBTNG database layer with usage examples and all API changes for both Themes and Modules Also includes an Appendix that introduces the beta release for Drupal 7. It is not a part of the book (print or e-book) but only available for free download Appendix         Read more about this book       Q: What is Drupal?A: Drupal is an Open Source Content Management System used for building dynamic websites.   Q: Why should I use Drupal and not any other CMS?A: By building on relevant standards and open source technologies, Drupal supports and enhances the potential of the Internet as a medium where diverse and geographically separated individuals and groups can collectively produce, discuss, and share information and ideas. With a central interest in and focus on communities and collaboration, Drupal's flexibility allows the collaborative production of online information systems and communities.   Q: What are the minimum requirements for Drupal 7?A: Drupal 7 requires PHP 5.2.0 or later to run the Drupal code. You will also need one of the following databases to run Drupal 7: MySQL version 5.0 or later PostgreSQL 8.3 or later SQLite 3.4.2 or later   Q: Where can one download Drupal 7 from?A: Head on over to http://drupal.org/project/drupal and click on the Drupal version number you wish to download—in this case it is Drupal 7. Click on Download and then save it to your C: drive or your My Documents folder (or wherever you want).   Q: What's new in Drupal 7?A: There are several key functionalities that made it to Drupal 7. Some of them are as follows: New administration toolbar and overlay administration: After installing Drupal 7 you will notice the new administration toolbar (shown in the following screenshot) that appears on all pages if you have the permission to administer the site: (Move the mouse over the image to enlarge it.) The toolbar groups commonly used tasks together making it easier for new administrators to learn how to configure Drupal and making it quicker for experienced administrators to get to commonly-used functionality. New Field API: The Field API allows site administrators to add additional attributes to a node type. It also supports translatable fields to allow for multi-lingual sites. Added context information to messages during translation: Drupal 7 adds an optional context for the translation to allow developers and themers to make translatable strings less ambiguous. Built-in automated cron functionality: Drupal 7 includes a new cron system that does not rely on running cron from the Unix cron system. The mechanism used is similar to the one used by poormanscron except that it runs from an AJAX request rather than delaying the response time of the page triggering cron. Added a new plugin manager: The plugin manager allows automatic updates of your Drupal installation. Seven theme for administration: A common complaint of Drupal administrators in previous versions was the look of the administration interface and that it could be difficult to tell when you were in the administration interface, since it used the same theme as regular content by default. To fix this, Drupal 7 has added a new administration theme called the Seven theme that is enabled by default. jQuery UI to core: jQuery UI (http://jqueryui.com) is a powerful JavaScript library that includes common controls like calendars, progress bars, tabs, sliders, and more. It also includes functionality to allow drag and drop, resizing, sorting, selection, and more. New Stark theme: The new Stark theme that is designed to make it easier to learn how to build a custom theme. Rewritten database layer (DBTNG): The biggest change in Drupal 7, at least for developers, is the new database layer, also called DBTNG (short for Database Layer: The Next Generation). DBTNG is a big change for developers since it changes how modules interact with the database. Queue API for long-running tasks: Drupal 7 adds a Queue API to manage long-running tasks. In general, any task that takes more than 30 seconds to a minute would be an excellent candidate for the Queue API. New test framework: Drupal 7 adds a comprehensive test framework called testing that allows developers and site administrators to run tests against an existing Drupal installation to ensure that it is behaving properly.   Q: How has the installation process improved in Drupal 7?A: Drupal 7 has a new installation routine. It is designed to make it easier for new Drupal users to set up Drupal. The new installation offers two types of install—the regular installation and a minimal installation.   The Minimal installation is similar to previous versions. The new Standard installation automatically enables commonly-used functionality during the installation to save time after setup.   Q: How has the interface for creating content and new content types improved in Drupal 7?A: Improved interface for creating content: A big, but welcome, change for editors is the redesigned and updated interface to create and edit content. A sample of the interface is shown in the following screenshot:   The redesigned screen makes it easier to quickly navigate to specific sections within the content. Improved interface for creating new content types: The interface for creating content types has been redesigned to keep all of the options in a smaller space so navigation is easier and all information can be quickly accessed.
Read more
  • 0
  • 0
  • 4990

article-image-cocos2d-iphone-handling-accelerometer-input-and-detecting-collisions
Packt
30 Dec 2010
4 min read
Save for later

Cocos2d for iPhone: Handling Accelerometer Input and Detecting Collisions

Packt
30 Dec 2010
4 min read
  Cocos2d for iPhone 0.99 Beginner's Guide Make mind-blowing 2D games for iPhone with this fast, flexible, and easy-to-use framework! A cool guide to learning cocos2d with iPhone to get you into the iPhone game industry quickly Learn all the aspects of cocos2d while building three different games Add a lot of trendy features such as particles and tilemaps to your games to captivate your players Full of illustrations, diagrams, and tips for building iPhone games, with clear step-by-step instructions and practical examples         Read more about this book       (For more resources on Cocos2d, see here.) Handling accelerometer input Now that we have our three basic elements roughly defined, let's focus on the player's interaction with the hero. We will start by allowing the player to move the hero using the device's built-in accelerometer. The accelerometer opens a new world of interaction between the user and the device, allowing for a lot of interesting uses. There are already lots of applications and games that use this feature in innovative ways. For example, in the game Rolando, players have to roll the main character around using the accelerometer, and here we will be doing something similar to that. The accelerometer gives you data of the current tilting of the device in the three axes, that is the x, y, and z axes. Depending on the game you are making, you will be needing all that data or just the values for one or two of the axis. Fortunately, Apple has made it very easy for developers to access the data provided by the accelerometer hardware. Time for action – moving your hero with the accelerometer We have to add a few lines of code in order to have our hero move. The end result will be the hero moving horizontally when the user tilts the device to the left or to the right. We will also do some checkovers, in order to avoid the hero moving out of the screen. The first step involved in using the accelerometer is to enable it for the CCLayers that want to receive its input. Add the following line of code to the GameLayer's init method: self.isAccelerometerEnabled = YES; Then we have to set the update interval for the accelerometer. This will set the interval at which the hardware delivers the data to the GameLayer. Add the following line afterwards: [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 60)]; Now that our GameLayer is prepared to receive accelerometer input, we just have to implement the method that receives and handles it. The following is the method that receives the input and makes our hero move. Add it to the GameLayer class: - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration{ static float prevX=0, prevY=0; #define kFilterFactor 0.05f float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX; prevX = accelX;//If the hero object exists, we use the calculated accelerometer values to move him if(hero) {//We calculate the speed it will have and constrain it so it doesn't move faster than he is allowed to float speed = -20 * -accelX; if(speed > hero.movementSpeed) speed = hero.movementSpeed; else if(speed < -hero.movementSpeed) speed = -hero.movementSpeed;//We also check that the hero won't go past the borders of the screen, if he would exit the screen we don't move it if((accelX >0 || hero.mySprite.position.x >hero.mySprite.textureRect.size.width / 2) && ( accelX <0 ||hero.mySprite.position.x <320- hero.mySprite.textureRect.size.width / 2)) [hero.mySprite setPosition:ccp(hero.mySprite.position.x +speed,hero.mySprite.position.y)]; }} Run the game now. You should be able to move the hero by tilting you device, as shown in the following screenshot: The iPhone simulator does not provide a way to simulate accelerometer input, so you won't be able to test it in there; it won't move at all. What just happened? Accelerometer input can be achieved quite easily and fast. In our example, we just used the x component of the accelerometer input to handle the hero's position. The accelX variable holds the current value of the x component. This value ranges from -1 to 1, so we multiply it by the speed of the hero, then we just add that result to the current position of the hero, giving the sense of motion. We are also checking to make sure that the hero is not going off the screen before applying that movement.
Read more
  • 0
  • 0
  • 5882

article-image-geo-spatial-data-python-working-geometry
Packt
29 Dec 2010
8 min read
Save for later

Geo-Spatial Data in Python: Working with Geometry

Packt
29 Dec 2010
8 min read
Python Geospatial Development Build a complete and sophisticated mapping application from scratch using Python tools for GIS development Build applications for GIS development using Python Analyze and visualize Geo-Spatial data Comprehensive coverage of key GIS concepts Recommended best practices for storing spatial data in a database Draw maps, place data points onto a map, and interact with maps A practical tutorial with plenty of step-by-step instructions to help you develop a mapping application from scratch         Read more about this book       (For more resources on Python, see here.) Working with Shapely geometries Shapely is a very capable library for performing various calculations on geo-spatial data. Let's put it through its paces with a complex, real-world problem. Task: Identify parks in or near urban areas The U.S. Census Bureau makes available a Shapefile containing something called Core Based Statistical Areas (CBSAs), which are polygons defining urban areas with a population of 10,000 or more. At the same time, the GNIS website provides lists of placenames and other details. Using these two datasources, we will identify any parks within or close to an urban area. Because of the volume of data we are potentially dealing with, we will limit our search to California. Feel free to download the larger data sets if you want, though you will have to optimize the code or your program will take a very long time to check all the CBSA polygon/placename combinations. Let's start by downloading the necessary data. Go to the TIGER website at http://census.gov/geo/www/tiger Click on the 2009 TIGER/Line Shapefiles Main Page link, then follow the Download the 2009 TIGER/Line Shapefiles now link. Choose California from the pop-up menu on the right, and click on Submit. A list of the California Shapefiles will be displayed; the Shapefile you want is labelled Metropolitan/Micropolitan Statistical Area. Click on this link, and you will download a file named tl_2009_06_cbsa.zip. Once the file has downloaded, uncompress it and place the resulting Shapefile into a convenient location so that you can work with it. You now need to download the GNIS placename data for California. Go to the GNIS website: http://geonames.usgs.gov/domestic Click on the Download Domestic Names hyperlink, and then choose California from the pop-up menu. You will be prompted to save the CA_Features_XXX.zip file. Do so, then decompress it and place the resulting CA_Features_XXX.txt file into a convenient place. The XXX in the above file name is a date stamp, and will vary depending on when you download the data. Just remember the name of the file as you'll need to refer to it in your source code. We're now ready to write the code. Let's start by reading through the CBSA urban area Shapefile and extracting the polygons that define the boundary of each urban area: shapefile = osgeo.ogr.Open("tl_2009_06_cbsa.shp")layer = shapefile.GetLayer(0)for i in range(layer.GetFeatureCount()): feature = layer.GetFeature(i) geometry = feature.GetGeometryRef() ... Make sure you add directory paths to your osgeo.ogr.Open() statement (and to the file() statement below) to match where you've placed these files. Using what we learned in the previous section, we can convert this geometry into a Shapely object so that we can work with it: wkt = geometry.ExportToWkt()shape = shapely.wkt.loads(wkt) Next, we need to scan through the CA_Features_XXX.txt file to identify the features marked as a park. For each of these features, we want to extract the name of the feature and its associated latitude and longitude. Here's how we might do this: f = file("CA_Features_XXX.txt", "r")for line in f.readlines(): chunks = line.rstrip().split("|") if chunks[2] == "Park": name = chunks[1] latitude = float(chunks[9]) longitude = float(chunks[10]) ... Remember that the GNIS placename database is a pipedelimited text file. That's why we have to split the line up using line.rstrip().split("|"). Now comes the fun part—we need to figure out which parks are within or close to each urban area. There are two ways we could do this, either of which will work: We could use the shape.distance() method to calculate the distance between the shape and a Point object representing the park's location: We could dilate the polygon using the shape.buffer() method, and then see if the resulting polygon contained the desired point: The second option is faster when dealing with a large number of points as we can pre-calculate the dilated polygons and then use them to compare against each point in turn. Let's take this option: # findNearbyParks.pyimport osgeo.ogrimport shapely.geometryimport shapely.wktMAX_DISTANCE = 0.1 # Angular distance; approx 10 km.print "Loading urban areas..."urbanAreas = {} # Maps area name to Shapely polygon.shapefile = osgeo.ogr.Open("tl_2009_06_cbsa.shp")layer = shapefile.GetLayer(0)for i in range(layer.GetFeatureCount()): feature = layer.GetFeature(i) name = feature.GetField("NAME") geometry = feature.GetGeometryRef() shape = shapely.wkt.loads(geometry.ExportToWkt()) dilatedShape = shape.buffer(MAX_DISTANCE) urbanAreas[name] = dilatedShapeprint "Checking parks..."f = file("CA_Features_XXX.txt", "r")for line in f.readlines(): chunks = line.rstrip().split("|") if chunks[2] == "Park": parkName = chunks[1] latitude = float(chunks[9]) longitude = float(chunks[10]) pt = shapely.geometry.Point(longitude, latitude) for urbanName,urbanArea in urbanAreas.items(): if urbanArea.contains(pt): print parkName + " is in or near " + urbanNamef.close() Don't forget to change the name of the CA_Features_XXX.txt file to match the actual name of the file you downloaded. You may also need to change the path names to the tl_2009_06_CBSA.shp file and the CA_Features file if you placed them in a different directory. If you run this program, you will get a master list of all the parks that are in or close to an urban area: % python findNearbyParks.pyLoading urban areas...Checking parks...Imperial National Wildlife Refuge is in or near El Centro, CATwinLakesStateBeach is in or near Santa Cruz-Watsonville, CAAdmiralWilliamStandleyState Recreation Area is in or near Ukiah, CAAgate Beach County Park is in or near San Francisco-Oakland-Fremont, CA... Note that our program uses angular distances to decide if a park is in or near a given urban area. An angular distance is the angle (in decimal degrees) between two rays going out from the center of the Earth to the Earth's surface. Because a degree of angular measurement (at least for the latitudes we are dealing with here) roughly equals 100 km on the Earth's surface, an angular measurement of 0.1 roughly equals a real distance of 10 km. Using angular measurements makes the distance calculation easy and quick to calculate, though it doesn't give an exact distance on the Earth's surface. If your application requires exact distances, you could start by using an angular distance to filter out the features obviously too far away, and then obtain an exact result for the remaining features by calculating the point on the polygon's boundary that is closest to the desired point, and then calculating the linear distance between the two points. You would then discard the points that exceed your desired exact linear distance. Converting and standardizing units of geometry and distance Imagine that you have two points on the Earth's surface with a straight line drawn between them: Each point can be described as a coordinate using some arbitrary coordinate system (for example, using latitude and longitude values), while the length of the straight line could be described as the distance between the two points. Given any two coordinates, it is possible to calculate the distance between them. Conversely, you can start with one coordinate, a desired distance and a direction, and then calculate the coordinates for the other point. Of course, because the Earth's surface is not flat, we aren't really dealing with straight lines at all. Rather, we are calculating geodetic or Great Circle distances across the surface of the Earth. The pyproj Python library allows you to perform these types of calculations for any given datum. You can also use pyproj to convert from projected coordinates back to geographic coordinates, and vice versa, allowing you to perform these sorts of calculations for any desired datum, coordinate system, and projection. Ultimately, a geometry such as a line or a polygon consists of nothing more than a list of connected points. This means that, using the above process, you can calculate the geodetic distance between each of the points in any polygon and total the results to get the actual length for any geometry. Let's use this knowledge to solve a realworld problem.  
Read more
  • 0
  • 0
  • 10495

article-image-enhancing-your-site-php-and-jquery
Packt
29 Dec 2010
12 min read
Save for later

Enhancing your Site with PHP and jQuery

Packt
29 Dec 2010
12 min read
  PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery Create rich and interactive web applications with PHP and jQuery Debug and execute jQuery code on a live site Design interactive forms and menus Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery         Read more about this book       (For more resources on this subject, see here.) Introduction In this article, we will look at some advanced techniques that can be used to enhance the functionality of web applications. We will create a few examples where we will search for images the from Flickr and videos from YouTube using their respective APIs. We will parse a RSS feed XML using jQuery and learn to create an endless scrolling page like Google reader or the new interface of Twitter. Besides this, you will also learn to create a jQuery plugin, which you can use independently in your applications. Sending cross-domain requests using server proxy Browsers do not allow scripts to send cross-domain requests due to security reasons. This means a script at domain http://www.abc.com cannot send AJAX requests to http://www.xyz.com. This recipe will show how you can overcome this limitation by using a PHP script on the server side. We will create an example that will search Flickr for images. Flickr will return a JSON, which will be parsed by jQuery and images will be displayed on the page. The following screenshot shows a JSON response from Flickr: Getting ready Create a directory for this article and name it as Article9. In this directory, create a folder named Recipe1. Also get an API key from Flickr by signing up at http://www.flickr.com/services/api/keys/. How to do it... Create a file inside the Recipe1 folder and name it as index.html. Write the HTML code to create a form with three fields: tag, number of images, and image size. Also create an ul element inside which the results will be displayed. <html> <head> <title>Flickr Image Search</title> <style type="text/css"> body { font-family:"Trebuchet MS",verdana,arial;width:900px; } fieldset { width:333px; } ul{ margin:0;padding:0;list-style:none; } li{ padding:5px; } span{ display:block;float:left;width:150px; } #results li{ float:left; } .error{ font-weight:bold; color:#ff0000; } </style> </head> <body> <form id="searchForm"> <fieldset> <legend>Search Criteria</legend> <ul> <li> <span>Tag</span> <input type="text" name="tag" id="tag"/> </li> <li> <span>Number of images</span> <select name="numImages" id="numImages"> <option value="20">20</option> <option value="30">30</option> <option value="40">40</option> <option value="50">50</option> </select> </li> <li> <span>Select a size</span> <select id="size"> <option value="s">Small</option> <option value="t">Thumbnail</option> <option value="-">Medium</option> <option value="b">Large</option> <option value="o">Original</option> </select> </li> <li> <input type="button" value="Search" id="search"/> </li> </ul> </fieldset> </form> <ul id="results"> </ul> </body> </html> The following screenshot shows the form created: Include the jquery.js file. Then, enter the jQuery code that will send the AJAX request to a PHP file search.php. Values of form elements will be posted with an AJAX request. A callback function showImages is also defined that actually reads the JSON response and displays the images on the page. <script type="text/javascript" src="../jquery.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#search').click(function() { if($.trim($('#tag').val()) == '') { $('#results').html('<li class="error">Please provide search criteria</li>'); return; } $.post( 'search.php', $('#searchForm').serialize(), showImages, 'json' ); }); function showImages(response) { if(response['stat'] == 'ok') { var photos = response.photos.photo; var str= ''; $.each(photos, function(index,value) { var farmId = value.farm; var serverId = value.server; var id = value.id; var secret = value.secret; var size = $('#size').val(); var title = value.title; var imageUrl = 'http://farm' + farmId + '.static.flickr.com/' + serverId + '/' + id + '_' + secret + '_' + size + '.jpg'; str+= '<li>'; str+= '<img src="' + imageUrl + '" alt="' + title + '" />'; str+= '</li>'; }); $('#results').html(str); } else { $('#results').html('<li class="error">an error occured</li>'); } } }); </script> Create another file named search.php. The PHP code in this file will contact the Flickr API with specified search criteria. Flickr will return a JSON that will be sent back to the browser where jQuery will display it on the page. <?php define('API_KEY', 'your-API-key-here'); $url = 'http://api.flickr.com/services/rest/?method=flickr. photos.search'; $url.= '&api_key='.API_KEY; $url.= '&tags='.$_POST['tag']; $url.= '&per_page='.$_POST['numImages']; $url.= '&format=json'; $url.= '&nojsoncallback=1'; header('Content-Type:text/json;'); echo file_get_contents($url); ?> Now, run the index.html file in your browser, enter a tag to search in the form, and select the number of images to be retrieved and image size. Click on the Search button. A few seconds later you will see the images from Flickr displayed on the page: <html> <head> <title>Youtube Video Search</title> <style type="text/css"> body { font-family:"Trebuchet MS",verdana,arial;width:900px; } fieldset { width:333px; } ul{ margin:0;padding:0;list-style:none; } li{ padding:5px; } span{ display:block;float:left;width:150px; } #results ul li{ float:left; background-color:#483D8B; color:#fff;margin:5px; width:120px; } .error{ font-weight:bold; color:#ff0000; } img{ border:0} </style> </head> <body> <form id="searchForm"> <fieldset> <legend>Search Criteria</legend> <ul> <li> <span>Enter query</span> <input type="text" id="query"/> </li> <li> <input type="button" value="Search" id="search"/> </li> </ul> </fieldset> </form> <div id="results"> </div> </body> </html> How it works... On clicking the Search button, form values are sent to the PHP file search.php. Now, we have to contact Flickr and search for images. Flickr API provides several methods for accessing images. We will use the method flickr.photos.search to search by tag name. Along with method name we will have to send the following parameters in the URL: api_key: An API key is mandatory. You can get one from: http://www.flickr.com/services/api/keys/. tags: The tags to search for. These can be comma-separated. This value will be the value of textbox tag. per_page: Number of images in a page. This can be a maximum of 99. Its value will be the value of select box numImages. format: It can be JSON, XML, and so on. For this example, we will use JSON. nojsoncallback: Its value will be set to 1 if we don't want Flickr to wrap the JSON in a function wrapper. Once the URL is complete we can contact Flickr to get results. To get the results' we will use the PHP function file_get_contents, which will get the results JSON from the specified URL. This JSON will be echoed to the browser. jQuery will receive the JSON in callback function showImages. This function first checks the status of the response. If the response is OK, we get the photo elements from the response and we can iterate over them using jQuery's $.each method. To display an image, we will have to get its URL first, which will be created by combining different values of the photo object. According to Flickr API specification, an image URL can be constructed in the following manner: http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[size].jpg So we get the farmId, serverId, id, and secret from the photo element. The size can be one of the following: s (small square) t (thumbnail) - (medium) b (large) o (original image) We have already selected the image size from the select box in the form. By combining all these values, we now have the Flickr image URL. We wrap it in a li element and repeat the process for all images. Finally, we insert the constructed images into the results li. Making cross-domain requests with jQuery The previous recipe demonstrated the use of a PHP file as a proxy for querying cross-domain URLs. This recipe will show the use of JSONP to query cross-domain URLs from jQuery itself. We will create an example that will search for the videos from YouTube and will display them in a list. Clicking on a video thumbnail will open a new window that will take the user to the YouTube website to show that video. The following screenshot shows a sample JSON response from YouTube: Getting ready Create a folder named Recipe2 inside the Article9 directory. How to do it... Create a file inside the Recipe2 folder and name it as index.html. Write the HTML code to create a form with a single field query and a DIV with results ID inside which the search results will be displayed. <script type="text/javascript" src="../jquery.js"></script> <script type="text/javascript"> $(document).ready(function() { $('#search').click(function() { var query = $.trim($('#query').val()); if(query == '') { $('#results').html('<li class="error">Please enter a query.</li>'); return; } $.get( 'http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script', {}, showVideoList, 'jsonp' ); }); }); function showVideoList(response) { var totalResults = response['feed']['openSearch$totalResults']['$t']; if(parseInt(totalResults,10) > 0) { var entries = response.feed.entry; var str = '<ul>'; for(var i=1; i< entries.length; i++) { var value = entries[i]; var title = value['title']['$t']; var mediaGroup = value['media$group']; var videoURL = mediaGroup['media$player'][0]['url']; var thumbnail = mediaGroup['media$thumbnail'][0]['url']; var thumbnailWidth = mediaGroup['media$thumbnail'][0]['width']; var thumbnailHeight = mediaGroup['media$thumbnail'][0]['height']; var numComments = value['gd$comments']['gd$feedLink']['countHint']; var rating = parseFloat(value['gd$rating']['average']).toFixed(2); str+= '<li>'; str+= '<a href="' + videoURL + '" target="_blank">'; str+= '<img src="'+thumbNail+'" width="'+thumbNailWidth+'" height="'+thumbNailWidth+'" title="' + title + '" />'; str+= '</a>'; str+= '<hr>'; str+= '<p style="width: 120px; font-size: 12px;">Comments: ' + numComments + ''; str+= '<br/>'; str+= 'Rating: ' + rating; str+= '</p>'; str+= '</li>'; } str+= '</ul>'; $('#results').html(str); } else { $('#results').html('<li class="error">No results.</li>'); } } </script> Include the jquery.js file before closing the &ltbody> tag. Now, write the jQuery code that will take the search query from the textbox and will try to retrieve the results from YouTube. A callback function called showVideoList will get the response and will create a list of videos from the response. http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script All done, and we are now ready to search YouTube. Run the index.html file in your browser and enter a search query. Click on the Search button and you will see a list of videos with a number of comments and a rating for each video. How it works... script tags are an exception to cross-browser origin policy. We can take advantage of this by requesting the URL from the src attribute of a script tag and by wrapping the raw response in a callback function. In this way the response becomes JavaScript code instead of data. This code can now be executed on the browser. The URL for YouTube video search is as follows: http://gdata.youtube.com/feeds/api/videos?q=' + query + '&alt=json-in-script Parameter q is the query that we entered in the textbox and alt is the type of response we want. Since we are using JSONP instead of JSON, the value for alt is defined as json-in-script as per YouTube API specification. On getting the response, the callback function showVideoList executes. It checks whether any results are available or not. If none are found, an error message is displayed. Otherwise, we get all the entry elements and iterate over them using a for loop. For each video entry, we get the videoURL, thumbnail, thumbnailWidth, thumbnailHeight, numComments, and rating. Then we create the HTML from these variables with a list item for each video. For each video an anchor is created with href set to videoURL. The video thumbnail is put inside the anchor and a p tag is created where we display the number of comments and rating for a particular video. After the HTML has been created, it is inserted in the DIV with ID results. There's more... About JSONP You can read more about JSONP at the following websites: http://remysharp.com/2007/10/08/what-is-jsonp/ http://en.wikipedia.org/wiki/JSON#JSONP
Read more
  • 0
  • 0
  • 8009

article-image-cocos2d-iphone-surfing-through-scenes
Packt
29 Dec 2010
10 min read
Save for later

Cocos2d for iPhone: Surfing Through Scenes

Packt
29 Dec 2010
10 min read
  Cocos2d for iPhone 0.99 Beginner's Guide Make mind-blowing 2D games for iPhone with this fast, flexible, and easy-to-use framework! A cool guide to learning cocos2d with iPhone to get you into the iPhone game industry quickly Learn all the aspects of cocos2d while building three different games Add a lot of trendy features such as particles and tilemaps to your games to captivate your players Full of illustrations, diagrams, and tips for building iPhone games, with clear step-by-step instructions and practical examples         Read more about this book       (For more resources on Cocos2d, see here.) We'll be doing a lot of things in this article, so let's get started. Aerial Gun, a vertical shooter game Let's talk about the game we will be making. Aerial Gun, as I said earlier, is a vertical shooter game. That means you will be in control of an airship which will move vertically. Actually, the airship won't be moving anywhere (well except to the left and right); what is really going to move here is the background, giving the sense the airship is the one moving. The player will be able to control the airship by using accelerometer controls. We'll also provide some areas where the player can touch to fire bullets or bombs to destroy the enemies. Enemies will be appearing at different time intervals and will have some different behaviors attached to them. For example, some of them could just move towards the airship, others may stay there and shoot back, and so on. We'll do it in a way you can create more custom behaviors later. For this game we will be using the Cocos2d template again, just because it is the easier way to have a project properly set up, at least to begin our work. So, follow the same steps as when we created the Coloured Stones game. Just open Xcode and go to the File menu, select to create a new project. Then choose the Cocos2d template (the simple one, without any physics engine) and give a name to the project. I will call it AerialGun. Once you do that, your new project should be opened. Creating new scenes We will begin this new game by first doing a couple of scenes other than the one that holds the actual game. If you take a look at the class that the template generates, at first sight you won't find what would appear to be a scene. That is because the template handles that in a confusing fashion, at least for people who are just getting started with Cocos2d. Let's take a look at that. Open the newly generated HelloWorldScene.m file. This is the same code in which we based our first game. This time we will analyze it so you understand what it is doing behind scenes. Take a look at the first method of the implementation of the HelloWorld Layer: +(id) scene{ // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. HelloWorld *layer = [HelloWorld node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene;} If you remember well, this is the method that get's called in the AppDelegate when the Director needs to start running with a scene. So why are we passing the method of a layer instead of an instance of a CCScene class? If you pay attention to the +(id)scene method of the layer, what it does is to instantiate a CCScene object, then it instantiates a HelloWorld object (the layer), and then it adds that layer to the scene and returns it. This actually works as you have witnessed and is pretty quick to set up, and get you up and running. However, sometimes you will need to have you own custom scenes, that is a class that inherits from CCScene and extends it in some fashion. Now we are going to create some of the scenes that we need for this game and add a layer to each one. Then when it is time to work with the game scene we will modify it to match our needs. Before doing anything, please change the name of the HelloWorldlayer to GameLayer and the name of the HelloWorldScene to GameScene, just as we did back then with our first game. Time for action – creating the splash and main menu scene We will begin with a simple scene, the splash screen. A splash screen is the first thing that appears as you launch a game. Well, the second if you count the Default.png image. The objective of this screen is to show the player some information about the developer, other companies that helped, and so on. Most times you will just show a couple and logos and move to the main menu. So, what we will do now is put a new Default.png image, then create the SplashScene. The Default.png image is located in your project's Resources group folder and it is the first image that is shown when the application is launched. You should always have one, so that something is shown while the application is being launched. This happens before anything is initialized, so you can't do anything else other than show this image. Its dimensions must be 320 * 480 (when developing for older generation iPhones), so if your game is supposed to be in landscape mode, you should rotate the image with any graphics software before including it in your project. The SplashScene is going to show a sprite for a moment, then fade it, show another one and then move to the GameScene. Let's add a new file to the project. Select New File (CMD + N) from the File menu, then select Objective-C class (we are going to do it from scratch anyways) and name it SplashScene. This file will hold both the SplashScene and the SplashLayer classes. The SplashLayer will be added as a child of the SplashScene, and inside the layer we will add the sprites. Before writing any code, add to the project the three splash images I created for you. You can find them in the companion files folder. Once you have them added into your project we can begin working on the SplashScene. The following is the SplashScene.h: #import <Foundation/Foundation.h>#import "cocos2d.h"#import "MainMenuScene.h"@interface SplashScene : CCScene { }@end@interface SplashLayer : CCLayer { }@end And the SplashScene.m file: #import "SplashScene.h" //Here is the implementation of the SplashScene@implementation SplashScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[SplashLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end//And here is the implementation of the SplashLayer@implementation SplashLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; NSMutableArray * splashImages = [[NSMutableArray alloc]init]; for(int i =1;i<=3;i++) { CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage]; } [self fadeAndShow:splashImages]; } return self;}//Now we add the methods that handle the image switching-(void)fadeAndShow:(NSMutableArray *)images{ if([images count]<=1) { [images release]; [[CCDirector sharedDirector]replaceScene:[MainMenuScene node]]; } else { CCSprite * actual = (CCSprite *)[images objectAtIndex:0]; [images removeObjectAtIndex:0]; CCSprite * next = (CCSprite *)[images objectAtIndex:0]; [actual runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeOut actionWithDuration:1],[CCCallFuncN actionWithTarget:self selector:@selector(remove:)],nil]]; [next runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeIn actionWithDuration:1],[CCDelayTime actionWithDuration:2], [CCCallFuncND actionWithTarget:self selector:@selector(cFadeAndShow: data:) data:images],nil]]; } }-(void) cFadeAndShow:(id)sender data:(void*)data{ NSMutableArray * images = (NSMutableArray *)data; [self fadeAndShow:images];}-(void)remove:(CCSprite *)s{ [s.parent removeChild:s cleanup:YES];}-(void)dealloc{ [super dealloc];}@end As you may notice, I have put together two classes in only one file. You can do this with any number of classes, as long you don't get lost in such a long file. Generally, you will create a pair of files (the .m and .h) for each class, but as the SplashScene class has very little code, I'd rather put it there. For this to work properly, we need to make some other changes. First, open the AerialGunAppDelegate.m file and change the line where the the Director starts running the GameScene. We want it to start by running the SplashScene now. So replace that line with the following: [[CCDirector sharedDirector] runWithScene:[SplashScene node]]; Also remember to import your SplashScene.h file in order for the project to properly compile. Finally, we have to create the MainMenuScene, which is the scene the Director will run after the last image has faded out. So, let's create that one and leave it blank for now. The following is the MainMenuScene.h file: #import <Foundation/Foundation.h>#import "cocos2d.h"@interface MainMenuScene : CCScene { }@end@interface MainMenuLayer : CCLayer { }@end The following is the MainMenuScene.m file: #import "MainMenuScene.h"@implementation MainMenuScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[MainMenuLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end@implementation MainMenuLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; } return self;}-(void)dealloc{ [super dealloc];}@end That would be all for now. Run the project and you should see the first image appear. Then fade to the next one after a while and continue till the last one. Once the last one has faded out, we move on to the MainMenuScene. What just happened? Creating a new scene is as easy as that. You can see from the MainMenuScene code that what we are doing is quite simple; when the MainMenuScene gets created we just instantiate the MainMenuLayer and add it to the scene. That layer is where we will later add all the necessary logic for the main menu. The MainMenuScene as well as the SplashScene both inherit from the CCScene class. This class is just another CCNode. Let's take a little look at the logic behind the SplashScene: NSMutableArray * splashImages = [[NSMutableArray alloc]init];for(int i =1;i<=3;i++){ CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage];} [self fadeAndShow:splashImages]; This piece of code is from the SplashLayer init method. What we are doing here is creating an array that will hold any amount of sprites (in this case, three of them). Then we create and add those sprites to it. Finally, the fadeAndShow method is called, passing that newly created array to it. The fadeAndShow method is responsible for fading the images it has. It grabs the first image in the array (after that, the sprite is removed from the array). It then grabs the next one. Then it applies actions to both of them to fade them in and out. The last action of the second sprite's action is a CCCallFuncND, which we use to call the fadeAndShow method again with the modified array. This occurs if there is more than one remaining sprite in the array. If there isn't, the fadeAndShow method calls the Director's replaceScene method with the MainMenuScene. I have made the SplashLayer logic, so you can add more splash images to the array (or leave just one) if you like. Generally, just one or two images will be more than enough.
Read more
  • 0
  • 0
  • 9208
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-granting-access-mysql-python
Packt
28 Dec 2010
10 min read
Save for later

Granting Access in MySQL for Python

Packt
28 Dec 2010
10 min read
MySQL for Python Integrate the flexibility of Python and the power of MySQL to boost the productivity of your Python applications Implement the outstanding features of Python's MySQL library to their full potential See how to make MySQL take the processing burden from your programs Learn how to employ Python with MySQL to power your websites and desktop applications Apply your knowledge of MySQL and Python to real-world problems instead of hypothetical scenarios A manual packed with step-by-step exercises to integrate your Python applications with the MySQL database server Introduction As with creating a user, granting access can be done by modifying the mysql tables directly. However, this method is error-prone and dangerous to the stability of the system and is, therefore, not recommended. Important dynamics of GRANTing access Where CREATE USER causes MySQL to add a user account, it does not specify that user's privileges. In order to grant a user privileges, the account of the user granting the privileges must meet two conditions: Be able to exercise those privileges in their account Have the GRANT OPTION privilege on their account Therefore, it is not just users who have a particular privilege or only users with the GRANT OPTION privilege who can authorize a particular privilege for a user, but only users who meet both requirements. Further, privileges that are granted do not take effect until the user's first login after the command is issued. Therefore, if the user is logged into the server at the time you grant access, the changes will not take effect immediately. The GRANT statement in MySQL The syntax of a GRANT statement is as follows: GRANT <privileges> ON <database>.<table> TO '<userid>'@'<hostname>'; Proceeding from the end of the statement, the userid and hostname follow the same pattern as with the CREATE USER statement. Therefore, if a user is created with a hostname specified as localhost and you grant access to that user with a hostname of '%', they will encounter a 1044 error stating access is denied. The database and table values must be specifi ed individually or collectively. This allows us to customize access to individual tables as necessary. For example, to specify access to the city table of the world database, we would use world.city. In many instances, however, you are likely to grant the same access to a user for all tables of a database. To do this, we use the universal quantifi er ('*'). So to specify all tables in the world database, we would use world.*. We can apply the asterisk to the database field as well. To specify all databases and all tables, we can use *.*. MySQL also recognizes the shorthand * for this. Finally, the privileges can be singular or a series of comma-separated values. If, for example, you want a user to only be able to read from a database, you would grant them only the SELECT privilege. For many users and applications, reading and writing is necessary but no ability to modify the database structure is warranted. In such cases, we can grant the user account both SELECT and INSERT privileges with SELECT, INSERT. To learn which privileges have been granted to the user account you are using, use the statement SHOW GRANTS FOR &ltuser>@hostname>;. With this in mind, if we wanted to grant a user tempo all access to all tables in the music database but only when accessing the server locally, we would use this statement: GRANT ALL PRIVILEGES ON music.* TO 'tempo'@'localhost'; Similarly, if we wanted to restrict access to reading and writing when logging in remotely, we would change the above statement to read: GRANT SELECT,INSERT ON music.* TO 'tempo'@'%'; If we wanted user conductor to have complete access to everything when logged in locally, we would use: GRANT ALL PRIVILEGES ON * TO 'conductor'@'localhost'; Building on the second example statement, we can further specify the exact privileges we want on the columns of a table by including the column numbers in parentheses after each privilege. Hence, if we want tempo to be able to read from columns 3 and 4 but only write to column 4 of the sheets table in the music database, we would use this command: GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%'; Note that specifying columnar privileges is only available when specifying a single database table—use of the asterisk as a universal quantifi er is not allowed. Further, this syntax is allowed only for three types of privileges: SELECT, INSERT, and UPDATE. A list of privileges that are available through MySQL is reflected in the following table: MySQL does not support the standard SQL UNDER privilege and does not support the use of TRIGGER until MySQL 5.1.6. More information on MySQL privileges can be found at http://dev.mysql.com/doc/refman/5.5/en/privileges-provided.html Using REQUIREments of access Using GRANT with a REQUIRE clause causes MySQL to use SSL encryption. The standard used by MySQL for SSL is the X.509 standard of the International Telecommunication Union's (ITU) Standardization Sector (ITU-T). It is a commonly used public-key encryption standard for single sign-on systems. Parts of the standard are no longer in force. You can read about the parts which still apply on the ITU website at http://www.itu.int/rec/T-REC-X.509/en The REQUIRE clause takes the following arguments with their respective meanings and follows the format of their respective examples: NONE: The user account has no requirement for an SSL connection. This is the default. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%'; SSL: The client must use an SSL-encrypted connection to log in. In most MySQL clients, this is satisfied by using the --ssl-ca option at the time of login. Specifying the key or certifi cate is optional. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' REQUIRE SSL; X509: The client must use SSL to login. Further, the certificate must be verifiable with one of the CA vendors. This option further requires the client to use the --ssl-ca option as well as specifying the key and certificate using --ssl-key and --ssl-cert, respectively. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' REQUIRE X509; CIPHER: Specifies the type and order of ciphers to be used. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' REQUIRE CIPHER 'RSA-EDH-CBC3-DES-SHA'; ISSUER: Specifies the issuer from whom the certificate used by the client is to come. The user will not be able to login without a certificate from that issuer. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' REQUIRE ISSUER 'C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division,CN=Thawte Server CA/emailAddress=server-certs@thawte. com'; SUBJECT: Specifies the subject contained in the certificate that is valid for that user. The use of a certificate containing any other subject is disallowed. GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' REQUIRE SUBJECT 'C=US, ST=California, L=Pasadena, O=Indiana Grones, OU=Raiders, CN=www.lostarks.com/ emailAddress=indy@lostarks.com'; Using a WITH clause MySQL's WITH clause is helpful in limiting the resources assigned to a user. WITH takes the following options: GRANT OPTION: Allows the user to provide other users of any privilege that they have been granted MAX_QUERIES_PER_HOUR: Caps the number of queries that the account is allowed to request in one hour MAX_UPDATES_PER_HOUR: Limits how frequently the user is allowed to issue UPDATE statements to the database MAX_CONNECTIONS_PER_HOUR: Limits the number of logins that a user is allowed to make in one hour MAX_USER_CONNECTIONS: Caps the number of simultaneous connections that the user can make at one time It is important to note that the GRANT OPTION argument to WITH has a timeless aspect. It does not statically apply to the privileges that the user has just at the time of issuance, but if left in effect, applies to any options the user has at any point in time. So, if the user is granted the GRANT OPTION for a temporary period, but the option is never removed, then the user grows in responsibilities and privileges, that user can grant those privileges to any other user. Therefore, one must remove the GRANT OPTION when it is not longer appropriate. Note also that if a user with access to a particular MySQL database has the ALTER privilege and is then granted the GRANT OPTION privilege, that user can then grant ALTER privileges to a user who has access to the mysql database, thus circumventing the administrative privileges otherwise needed. The WITH clause follows all other options given in a GRANT statement. So, to grant user tempo the GRANT OPTION, we would use the following statement: GRANT SELECT (col3,col4),INSERT (col4) ON music.sheets TO 'tempo'@'%' WITH GRANT OPTION; If we want to limit the number of queries that the user can have in one hour to five, as well, we simply add to the argument of the single WITH statement. We do not need to use WITH a second time. GRANT SELECT,INSERT ON music.sheets TO 'tempo'@'%' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 5; More information on the many uses of WITH can be found at http://dev.mysql.com/doc/refman/5.1/en/grant.html Granting access in Python Using MySQLdb to enable user privileges is not more difficult than doing so in MySQL itself. As with creating and dropping users, we simply need to form the statement and pass it to MySQL through the appropriate cursor. As with the native interface to MySQL, we only have as much authority in Python as our login allows. Therefore, if the credentials with which a cursor is created has not been given the GRANT option, an error will be thrown by MySQL and MySQLdb, subsequently. Assuming that user skipper has the GRANT option as well as the other necessary privileges, we can use the following code to create a new user, set that user's password, and grant that user privileges: #!/usr/bin/env python import MySQLdb host = 'localhost' user = 'skipper' passwd = 'secret' mydb = MySQLdb.connect(host, user, passwd) cursor = mydb.cursor() try: mkuser = 'symphony' creation = "CREATE USER %s@'%s'" %(mkuser, host) results = cursor.execute(creation) print "User creation returned", results mkpass = 'n0n3wp4ss' setpass = "SET PASSWORD FOR '%s'@'%s' = PASSWORD('%s')" %(mkuser, host, mkpass) results = cursor.execute(setpass) print "Setting of password returned", results granting = "GRANT ALL ON *.* TO '%s'@'%s'" %(mkuser, host) results = cursor.execute(granting) print "Granting of privileges returned", results except MySQLdb.Error, e: print e If there is an error anywhere along the way, it is printed to screen. Otherwise, the several print statements are executed. As long as they all return 0, each step was successful.
Read more
  • 0
  • 0
  • 12651

article-image-getting-started-ext-gwt
Packt
28 Dec 2010
8 min read
Save for later

Getting Started with Ext GWT

Packt
28 Dec 2010
8 min read
  Ext GWT 2.0: Beginner's Guide Take the user experience of your website to a new level with Ext GWT Explore the full range of features of the Ext GWT library through practical, step-by-step examples Discover how to combine simple building blocks into powerful components Create powerful Rich Internet Applications with features normally only found in desktop applications Learn how to structure applications using MVC for maximum reliability and maintainability      What is GWT missing? GWT is a toolkit as opposed to a full development framework, and for most projects, it forms the part of a solution rather than the whole solution. Out-of-the-box GWT comes with only a basic set of widgets and lacks a framework to enable the developers to structure larger applications. Fortunately, GWT is both open and extensible and as a result, a range of complementary projects have grown up around it. Ext GWT is one of those projects. What does Ext GWT offer? Ext GWT sets out to build upon the strengths of GWT by enabling the developers to give their users an experience more akin to that of a desktop application. Ext GWT provides the GWT developer with a comprehensive component library similar to that used when developing for desktop environments. In addition to being a component library, powerful features for working with local and remote data are provided. It also features a model view controller framework, which can be used to structure larger applications. How is Ext GWT licensed? Licensing is always an important consideration when choosing technology to use in a project. At the time of writing, Ext GWT is offered with a dual license. The first license is an open source license compatible with the GNU GPL license v3. If you wish to use this license, you do not have to pay a fee for using Ext GWT, but in return you have to make your source code available under an open source license. This means you have to contribute all the source code of your project to the open source community and give everyone the right to modify or redistribute it. If you cannot meet the obligations of the open source license, for example, you are producing a commercial product or simply do not want to share your source code, you have to purchase a commercial license for Ext GWT. It is a good idea to check the current licensing requirements on the Sencha website, http://www.sencha.com, and take that into account when planning your project. Alternatives to Ext GWT Ext GWT is one of the many products produced by the company Sencha. Sencha was previously named Ext JS and started off developing a JavaScript library by the same name. Ext GWT is closely related to the Ext JS product in terms of functionality. Both Ext GWT and Ext JS also share the same look and feel as well as a similar API structure. However, Ext GWT is a native GWT implementation, written almost entirely in Java rather than a wrapper, the JavaScript-based Ext JS. GWT-Ext Before Ext GWT, there was GWT-Ext: http://code.google.com/p/gwt-ext/. This library was developed by Sanjiv Jeevan as a GWT wrapper around an earlier, 2.0.2 version of Ext JS. Being based on Ext JS, it has a very similar look and feel to Ext GWT. However, after the license of Ext JS changed from LGPL to GPL in 2008, active development came to an end. Apart from no longer being developed or supported, developing with GWT-Ext is more difficult than with Ext GWT. This is because the library is a wrapper around JavaScript and the Java debugger cannot help when there is a problem in the JavaScript code. Manual debugging is required. Smart GWT When development of GWT-Ext came to an end, Sanjiv Jeevan started a new project named Smart GWT: http://www.smartclient.com/smartgwt/. This is a LGPL framework that wraps the Smart Client JavaScript library in a similar way that GWT-Ext wraps Ext JS. Smart GWT has the advantage that it is still being actively developed. Being LGPL-licensed, it also can be used commercially without the need to pay the license fee that is required for Ext GWT. Smart GWT still has the debugging problems of GWT-Ext and the components are often regarded not as visually pleasing as Ext GWT. This could be down to personal taste of course. Vaadin Vaadin, http://vaadin.com, is a third alternative to Ext GWT. Vaadin is a server-side framework that uses a set of precompiled GWT components. Although you can write your own components if required, Vaadin is really designed so that you can build applications by combining the ready-made components. In Vaadin the browser client is just a dumb view of the server components and any user interaction is sent to the server for processing much like traditional Java web frameworks. This can be slow depending on the speed of the connection between the client and the server. The main disadvantage of Vaadin is the dependency on the server. GWT or Ext GWT's JavaScript can run in a browser without needing to communicate with a server. This is not possible in Vaadin. Ext GWT or GXT? To avoid confusion with GWT-Ext and to make it easier to write, Ext GWT is commonly abbreviated to GXT. We will use GXT synonymously with Ext GWT throughout the rest of this article. Working with GXT: A different type of web development If you are a web developer coming to GXT or GWT for the first time, it is very important to realize that working with this toolset is not like traditional web development. In traditional web development, most of the work is done on the server and the part the browser plays is li?? le more than a view-making request and receiving responses. When using GWT, especially GXT, at times it is easier if you suspend your web development thinking and think more like a desktop-rich client developer. Java Swing developers, for example, may find themselves at home. How GXT fits into GWT GXT is simply a library that plugs into any GWT project. If we have an existing GWT project setup, all we need to do to use it is: Download the GXT SDK from the Sencha website Add the library to the project and reference it in the GWT configuration Copy a set of resource files to the project If you haven't got a GWT project setup, don't worry. We will now work through getting GXT running from the beginning. Downloading what you need Before we can start working with GXT, we first need to download the toolkit and set up our development environment. Here is the list of what you need to download for running the examples.     Recommended Notes Download from Sun JDK 6 The Java development kit http://java.sun.com/javase/downloads/widget/jdk6.jsp Eclipse IDE for Java EE Developers 3.6 The Eclipse IDE for Java developers, which also includes some useful web development tools http://www.eclipse.org/downloads/ Ext GWT 2.2.0 SDK for GWT 2.0 The GXT SDK itself http://www.sencha.com/products/gwt/download.php Google supplies a useful plugin that integrates GWT into Eclipse. However, there is no reason that you cannot use an alternative development environment, if you prefer. Eclipse setup There are different versions of Eclipse, and although Eclipse for Java EE developers is not strictly required, it contains some useful tools for editing web-specific files such as CSS. These tools will be useful for GXT development, so it is strongly recommended. We will not cover the details of installing Eclipse here, as this is covered more than adequately on the Eclipse website. For that reason, we make the assumption that you already have a fresh installation of Eclipse ready to go. GWT setup You may have noticed that GWT is not included in the list of downloads. This is because since version 2.0.0, GWT has been available within an Eclipse plugin, which we will now set up. Time for action – setting up GWT In Eclipse, select Help Install New Software|. The installation dialog will appear. Click on the Add button to add a new site. Enter the name and location in the respective fields, as shown in the following screenshot, and click on the OK button. Move the mouse over the image to enlarge it. Select Google Plugin for Eclipse from the plugin section and Google Web Toolkit SDK from the SDKs section. Click on Next. The following dialog will appear. Click on Next to proceed. Click on the radio button to accept the license. Click on Finish. Eclipse will now download the Google Web Toolkit and configure the plugin. Restart when prompted. On restarting, if GWT and the Google Eclipse Plugin are installed successfully, you will notice the following three new icons in your toolbar. What just happened? You have now set up GWT in your Eclipse IDE. You are now ready to create GWT applications. However, before we can create GXT applications, there is a bit more work to do.
Read more
  • 0
  • 0
  • 5482

article-image-python-testing-mock-objects
Packt
28 Dec 2010
13 min read
Save for later

Python Testing: Mock Objects

Packt
28 Dec 2010
13 min read
How to install Python Mocker Python Mocker isn't included in the standard Python distribution. That means that we need to download and install it. Time for action – installing Python Mocker At the time of this writing, Python Mocker's home page is located at http://labix.org/mocker, while its downloads are hosted at https://launchpad.net/mocker/+download. Go ahead and download the newest version, and we'll see about installing it. The first thing that needs to be done is to unzip the downloaded file. It's a .tar.bz2, which should just work for Unix, Linux, or OSX users. Windows users will need a third-party program (7-Zip works well: http://www.7-zip.org/) to uncompress the archive. Store the uncompressed file in some temporary location. Once you have the files unzipped somewhere, go to that location via the command line. Now, to do this next step, you either need to be allowed to write files into your Python installation's site-packages directory (which you are, if you're the one who installed Python in the first place) or you need to be using Python version 2.6 or higher. If you can write to site-packages, type $ python setup.py install If you can't write to site-packages, but you're using Python 2.6 or higher, type $ python setup.py install --user Sometimes, a tool called easy_install can simplify the installation process of Python modules and packages. If you want to give it a try, download and install setuptools from http://pypi.python.org/pypi/setuptools, according to the directions on that page, and then run the command easy_install mocker. Once that command is done, you should be ready to use Nose. Once you have successfully run the installer, Python Mocker is ready for use. What is a mock object in software testing? "Mock" in this sense means "imitation," and that's exactly what a mock object does. Mock objects imitate the real objects that make up your program, without actually being those objects or relying on them in any way. Instead of doing whatever the real object would do, a mock object performs predefined simple operations that look like what the real object should do. That means its methods return appropriate values (which you told it to return) or raise appropriate exceptions (which you told it to raise). A mock object is like a mockingbird; imitating the calls of other birds without comprehending them. We've already used one mock object in our earlier work when we replaced time.time with an object (in Python, functions are objects) that returned an increasing series of numbers. The mock object was like time.time, except that it always returned the same series of numbers, no matter when we ran our test or how fast the computer was that we ran it on. In other words, it decoupled our test from an external variable. That's what mock objects are all about: decoupling tests from external variables. Sometimes those variables are things like the external time or processor speed, but usually the variables are the behavior of other units. Python Mocker The idea is pretty straightforward, but one look at that mock version of time.time shows that creating mock objects without using a toolkit of some sort can be a dense and annoying process, and can interfere with the readability of your tests. This is where Python Mocker (or any of several other mock object toolkits, depending on preference) comes in. Time for action – exploring the basics of Mocker We'll walk through some of the simplest—and most useful—features of Mocker. To do that, we'll write tests that describe a class representing a specific mathematical operation (multiplication) which can be applied to the values of arbitrary other mathematical operation objects. In other words, we'll work on the guts of a spreadsheet program (or something similar). We're going to use Mocker to create mock objects to stand in place of the real operation objects. Create up a text file to hold the tests, and add the following at the beginning (assuming that all the mathematical operations will be defined in a module called operations): >>> from mocker import Mocker >>> import operations We've decided that every mathematical operation class should have a constructor accepting the objects representing the new object's operands. It should also have an evaluate function that accepts a dictionary of variable bindings as its parameter and returns a number as the result. We can write the tests for the constructor fairly easily, so we do that first (Note that we've included some explanation in the test file, which is always a good idea): We're going to test out the constructor for the multiply operation, first. Since all that the constructor has to do is record all of the operands, this is straightforward. >>> mocker = Mocker() >>> p1 = mocker.mock() >>> p2 = mocker.mock() >>> mocker.replay() >>> m = operations.multiply(p1, p2) >>> m.operands == (p1, p2) True >>> mocker.restore() >>> mocker.verify() The tests for the evaluate method are somewhat more complicated, because there are several things we need to test. This is also where we start seeing the real advantages of Mocker: Now we're going to check the evaluate method for the multiply operation. It should raise a ValueError if there are less than two operands, it should call the evaluate methods of all operations that are operands of the multiply, and of course it should return the correct value. >>> mocker = Mocker() >>> p1 = mocker.mock() >>> p1.evaluate({}) #doctest: +ELLIPSIS <mocker.Mock object at ...> >>> mocker.result(97.43) >>> mocker.replay() >>> m = operations.multiply(p1) >>> m.evaluate({}) Traceback (most recent call last): ValueError: multiply without at least two operands is meaningless >>> mocker.restore() >>> mocker.verify() >>> mocker = Mocker() >>> p1 = mocker.mock() >>> p1.evaluate({}) #doctest: +ELLIPSIS <mocker.Mock object at ...> >>> mocker.result(97.43) >>> p2 = mocker.mock() >>> p2.evaluate({}) #doctest: +ELLIPSIS <mocker.Mock object at ...> >>> mocker.result(-16.25) >>> mocker.replay() >>> m = operations.multiply(p1, p2) >>> round(m.evaluate({}), 2) -1583.24 >>> mocker.restore() >>> mocker.verify() If we run the tests now, we get a list of failed tests. Most of them are due to Mocker being unable to import the operations module, but the bottom of the list should look like this: Finally, we'll write some code in the operations module that passes these tests, producing the following: class multiply: def __init__(self, *operands): self.operands = operands def evaluate(self, bindings): vals = [x.evaluate(bindings) for x in self.operands] if len(vals) < 2: raise ValueError('multiply without at least two ' 'operands is meaningless') result = 1.0 for val in vals: result *= val return result Now when we run the tests, none of them should fail. What just happened? The difficulty in writing the tests for something like this comes(as it often does) from the need to decouple the multiplication class from all of the other mathematical operation classes, so that the results of the multiplication test only depend on whether multiplication works correctly. We addressed this problem by using the Mocker framework for mock objects. The way Mocker works is that you first create an object representing the mocking context, by doing something such as mocker = Mocker(). The mocking context will help you create mock objects, and it will store information about how you expect them to be used. Additionally, it can help you temporarily replace library objects with mocks (like we've previously done with time.time) and restore the real objects to their places when you're done. We'll see more about doing that in a little while. Once you have a mocking context, you create a mock object by calling its mock method, and then you demonstrate how you expect the mock objects to be used. The mocking context records your demonstration, so later on when you call its replay method it knows what usage to expect for each object and how it should respond. Your tests (which use the mock objects instead of the real objects that they imitate), go after the call to replay. Finally, after test code has been run, you call the mocking context's restore method to undo any replacements of library objects, and then verify to check that the actual usage of the mocks was as expected. Our first use of Mocker was straightforward. We tested our constructor, which is specified to be extremely simple. It's not supposed to do anything with its parameters, aside from store them away for later. Did we gain anything at all by using Mocker to create mock objects to use as the parameters, when the parameters aren't even supposed to do anything? In fact, we did. Since we didn't tell Mocker to expect any interactions with the mock objects, it will report nearly any usage of the parameters (storing them doesn't count, because storing them isn't actually interacting with them) as errors during the verify step. When we call mocker.verify(), Mocker looks back at how the parameters were really used and reports a failure if our constructor tried to perform some action on them. It's another way to embed our expectations into our tests. We used Mocker twice more, except in those later uses we told Mocker to expect a call to an evaluate method on the mock objects (i.e. p1 and p2), and to expect an empty dictionary as the parameter to each of the mock objects' evaluate call. For each call we told it to expect, we also told it that its response should be to return a specific floating point number. Not coincidentally, that mimics the behavior of an operation object, and we can use the mocks in our tests of multiply.evaluate. If multiply.evaluate hadn't called the evaluate methods of mock, or if it had called one of them more than once, our mocker.verify call would have alerted us to the problem. This ability to describe not just what should be called but how often each thing should be called is a very useful too that makes our descriptions of what we expect much more complete. When multiply.evaluate calls the evaluate method of mock, the values that get returned are the ones that we specified, so we know exactly what multiply.evaluate ought to do. We can test it thoroughly, and we can do it without involving any of the other units of our code. Try changing how multiply.evaluate works and see what mocker.verify says about it. Mocking functions Normal objects (that is to say, objects with methods and attributes created by instantiating a class) aren't the only things you can make mocks of. Functions are another kind of object that can be mocked, and it turns out to be pretty easy. During your demonstration, if you want a mock object to represent a function, just call it. The mock object will recognize that you want it to behave like a function, and it will make a note of what parameters you passed it, so that it can compare them against what gets passed to it during the test. For example, the following code creates a mock called func, which pretends to be a function that, when called once with the parameters 56 and hello, returns the number 11. The second part of the example uses the mock in a very simple test: >>> from mocker import Mocker >>> mocker = Mocker() >>> func = mocker.mock() >>> func(56, "hello") # doctest: +ELLIPSIS <mocker.Mock object at ...> >>> mocker.result(11) >>> mocker.replay() >>> func(56, "hello") 11 >>> mocker.restore() >>> mocker.verify() Mocking containers Containers are another category of somewhat special objects that can be mocked. Like functions, containers can be mocked by simply using a mock object as if it were a container during your example. Mock objects are able to understand examples that involve the following container operations: looking up a member, setting a member, deleting a member, finding the length, and getting an iterator over the members. Depending on the version of Mocker, membership testing via the in operator may also be available. In the following example, all of the above capabilities are demonstrated, but the in tests are disabled for compatibility with versions of Mocker that don't support them. Keep in mind that even though, after we call replay, the object called container looks like an actual container, it's not. It's just responding to stimuli we told it to expect, in the way we told it to respond. That's why, when our test asks for an iterator, it returns None instead. That's what we told it to do, and that's all it knows. >>> from mocker import Mocker >>> mocker = Mocker() >>> container = mocker.mock() >>> container['hi'] = 18 >>> container['hi'] # doctest: +ELLIPSIS <mocker.Mock object at ...> >>> mocker.result(18) >>> len(container) 0 >>> mocker.result(1) >>> 'hi' in container # doctest: +SKIP True >>> mocker.result(True) >>> iter(container) # doctest: +ELLIPSIS <...> >>> mocker.result(None) >>> del container['hi'] >>> mocker.result(None) >>> mocker.replay() >>> container['hi'] = 18 >>> container['hi'] 18 >>> len(container) 1 >>> 'hi' in container # doctest: +SKIP True >>> for key in container: ... print key Traceback (most recent call last): TypeError: iter() returned non-iterator of type 'NoneType' >>> del container['hi'] >>> mocker.restore() >>> mocker.verify() Something to notice in the above example is that during the initial phase, a few of the demonstrations (for example, the call to len) did not return a mocker.Mock object, as we might have expected. For some operations, Python enforces that the result is of a particular type (for example, container lengths have to be integers), which forces Mocker to break its normal pattern. Instead of returning a generic mock object, it returns an object of the correct type, although the value of the returned object is meaningless. Fortunately, this only applies during the initial phase, when you're showing Mocker what to expect, and only in a few cases, so it's usually not a big deal. There are times when the returned mock objects are needed, though, so it's worth knowing about the exceptions.
Read more
  • 0
  • 0
  • 5567

article-image-wxpython-28-window-layout-and-design
Packt
24 Dec 2010
8 min read
Save for later

wxPython 2.8: Window Layout and Design

Packt
24 Dec 2010
8 min read
wxPython 2.8 Application Development Cookbook Over 80 practical recipes for developing feature-rich applications using wxPython Develop flexible applications in wxPython. Create interface translatable applications that will run on Windows, Macintosh OSX, Linux, and other UNIX like environments. Learn basic and advanced user interface controls. Packed with practical, hands-on cookbook recipes and plenty of example code, illustrating the techniques to develop feature-rich applications using wxPython.        Once you have an idea of how the interface of your applications should look, it comes the time to put it all together. Being able to take your vision and translate it into code can be a tricky and often tedious task. A window's layout is defined on a two dimensional plane with the origin being the window's top-left corner. All positioning and sizing of any widgets, no matter what it's onscreen appearance, is based on rectangles. Clearly understanding these two basic concepts goes a long way towards being able to understand and efficiently work with the toolkit. Traditionally in older applications, window layout was commonly done by setting explicit static sizes and positions for all the controls contained within a window. This approach, however, can be rather limiting as the windows will not be resizable, they may not fit on the screen under different resolutions, trying to support localization becomes more difficult because labels and other text will differ in length in different languages, the native widgets will often be different sizes on different platforms making it difficult to write platform independent code, and the list goes on. So, you may ask what the solution to this is. In wxPython, the method of choice is to use the Sizer classes to define and manage the layout of controls. Sizers are classes that manage the size and positioning of controls through an algorithm that queries all of the controls that have been added to the Sizer for their recommended best minimal sizes and their ability to stretch or not, if the amount of available space increases, such as if a user makes a dialog bigger. Sizers also handle cross-platform widget differences, for example, buttons on GTK tend to have an icon and be generally larger than the buttons on Windows or OS X. Using a Sizer to manage the button's layout will allow the rest of the dialog to be proportionally sized correctly to handle this without the need for any platform-specific code. So let us begin our adventure into the world of window layout and design by taking a look at a number of the tools that wxPython provides in order to facilitate this task. Using a BoxSizer A BoxSizer is the most basic of Sizer classes. It supports a layout that goes in a single direction—either a vertical column or a horizontal row. Even though it is the most basic to work with, a BoxSizer is one of the most useful Sizer classes and tends to produce more consistent cross-platform behavior when compared to some of the other Sizers types. This recipe creates a simple window where we want to have two text controls stacked in a vertical column, each with a label to the left of it. This will be used to illustrate the most simplistic usage of a BoxSizer in order to manage the layout of a window's controls. How to do it... Here we define our top level Frame, which will use a BoxSizer to manage the size of its Panel: class BoxSizerFrame(wx.Frame): def __init__(self, parent, *args, **kwargs): super(BoxSizerFrame, self).__init__(*args, **kwargs)         # Attributes self.panel = BoxSizerPanel(self)         # Layout sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.panel, 1, wx.EXPAND) self.SetSizer(sizer) self.SetInitialSize() The BoxSizerPanel class is the next layer in the window hierarchy, and is where we will perform the main layout of the controls: class BoxSizerPanel(wx.Panel): def __init__(self, parent, *args, **kwargs): super(BoxSizerPanel, self).__init__(*args, **kwargs)         # Attributes self._field1 = wx.TextCtrl(self) self._field2 = wx.TextCtrl(self)         # Layout self._DoLayout() Just to help reduce clutter in the __init__ method, we will do all the layout in a separate _DoLayout method: def _DoLayout(self): """Layout the controls""" vsizer = wx.BoxSizer(wx.VERTICAL) field1_sz = wx.BoxSizer(wx.HORIZONTAL) field2_sz = wx.BoxSizer(wx.HORIZONTAL)     # Make the labels field1_lbl = wx.StaticText(self, label="Field 1:") field2_lbl = wx.StaticText(self, label="Field 2:")     # Make the first row by adding the label and field # to the first horizontal sizer field1_sz.AddSpacer(50) field1_sz.Add(field1_lbl) field1_sz.AddSpacer(5) # put 5px of space between field1_sz.Add(self._field1) field1_sz.AddSpacer(50) # Do the same for the second row field2_sz.AddSpacer(50) field2_sz.Add(field2_lbl) field2_sz.AddSpacer(5) field2_sz.Add(self._field2) field2_sz.AddSpacer(50)     # Now finish the layout by adding the two sizers # to the main vertical sizer. vsizer.AddSpacer(50) vsizer.Add(field1_sz) vsizer.AddSpacer(15) vsizer.Add(field2_sz) vsizer.AddSpacer(50)     # Finally assign the main outer sizer to the panel self.SetSizer(vsizer) How it works... The previous code shows the basic pattern of how to create a simple window layout programmatically, using sizers to manage the controls. First let's start by taking a look at the BoxSizerPanel class's _DoLayout method, as this is where the majority of the layout in this example takes place. First, we started off by creating three BoxSizer classes: one with a vertical orientation, and two with a horizontal orientation. The layout we desired for this window requires us to use three BoxSizer classes and this is why. If you break down what we want to do into simple rectangles, you will see that: We wanted two TextCtrl objects each with a label to the left of them which can simply be thought of as two horizontal rectangles. We wanted the TextCtrl objects stacked vertically in the window which is just a vertical rectangle that will contain the other two rectangles. This is illustrated by the following screenshot (borders are drawn in and labels are added to show the area managed by each of Panel's three BoxSizers): In the section where we populate the first horizontal sizer (field1_sz), we use two of the BoxSizer methods to add items to the layout. The first is AddSpacer, which does simply as its named and adds a fixed amount of empty space in the left-hand side of the sizer. Then we use the Add method to add our StaticText control to the right of the spacer, and continue from here to add other items to complete this row. As you can see, these methods add items to the layout from left to right in the sizer. After this, we again do the same thing with the other label and TextCtrl in the second horizontal sizer. The last part of the Panel's layout is done by adding the two horizontal sizers to the vertical sizer. This time, since the sizer was created with a VERTICAL orientation, the items are added from top to bottom. Finally, we use the Panel's SetSizer method to assign the main outer BoxSizer as the Panel's sizer. The BoxSizerFrame also uses a BoxSizer to manage the layout of its Panel. The only difference here is that we used the Add method's proportion and flags parameters to tell it to make the Panel expand to use the entire space available. After setting the Frame's sizer, we used its SetInitialSize method, which queries the window's sizer and its descendents to get and set the best minimal size to set the window to. We will go into more detail about these other parameters and their effects in the next recipe. There's more... Included below is a little more additional information about adding spacers and items to a sizer's layout. Spacers The AddSpacer will add a square-shaped spacer that is X pixels wide by X pixels tall to the BoxSizer, where X is the value passed to the AddSpacer method. Spacers of other dimensions can be added by passing a tuple as the first argument to the BoxSizer's Add method. someBoxSizer.Add((20,5)) This will add a 20x5 pixel spacer to the sizer. This can be useful when you don't want the vertical space to be increased by as much as the horizontal space, or vice versa. AddMany The AddMany method can be used to add an arbitrary number of items to the sizer in one call. AddMany takes a list of tuples that contain values that are in the same order as the Add method expects. someBoxSizer.AddMany([(staticText,), ((10, 10),), (txtCtrl, 0, wx.EXPAND)])) This will add three items to the sizer: the first two items only specify the one required parameter, and the third specifies the proportion and flags parameters.
Read more
  • 0
  • 0
  • 2659
article-image-python-built-functions
Packt
24 Dec 2010
10 min read
Save for later

Python Built-in Functions

Packt
24 Dec 2010
10 min read
  Python 3 Object Oriented Programming Harness the power of Python 3 objects Learn how to do Object Oriented Programming in Python using this step-by-step tutorial Design public interfaces using abstraction, encapsulation, and information hiding Turn your designs into working software by studying the Python syntax Raise, handle, define, and manipulate exceptions using special error objects Implement Object Oriented Programming in Python using practical examples         Read more about this book       (For more resources on Python, see here.) There are numerous functions in Python that perform a task or calculate a result on certain objects without being methods on the class. Their purpose is to abstract common calculations that apply to many types of classes. This is applied duck typing; these functions accept objects with certain attributes or methods that satisfy a given interface, and are able to perform generic tasks on the object. Len The simplest example is the len() function. This function counts the number of items in some kind of container object such as a dictionary or list. For example: >>> len([1,2,3,4])4 Why don't these objects have a length property instead of having to call a function on them? Technically, they do. Most objects that len() will apply to have a method called __len__() that returns the same value. So len(myobj) seems to callmyobj.__len__(). Why should we use the function instead of the method? Obviously the method is a special method with double-underscores suggesting that we shouldn't call it directly. There must be an explanation for this. The Python developers don't make such design decisions lightly. The main reason is efficiency. When we call __len__ on an object, the object has to look the method up in its namespace, and, if the special __getattribute__ method (which is called every time an attribute or method on an object is accessed) is defined on that object, it has to be called as well. Further __getattribute__ for that particular method may have been written to do something nasty like refusing to give us access to special methods such as __len__! The len function doesn't encounter any of this. It actually calls the __len__ function on the underlying class, so len(myobj) maps to MyObj.__len__(myobj). Another reason is maintainability. In the future, the Python developers may want to change len() so that it can calculate the length of objects that don't have a __len__, for example by counting the number of items returned in an iterator. They'll only have to change one function instead of countless __len__ methods across the board. Reversed The reversed() function takes any sequence as input, and returns a copy of that sequence in reverse order. It is normally used in for loops when we want to loop over items from back to front. Similar to len, reversed calls the __reversed__() function on the class for the parameter. If that method does not exist, reversed builds the reversed sequence itself using calls to __len__ and __getitem__. We only need to override __reversed__ if we want to somehow customize or optimize the process: normal_list=[1,2,3,4,5]class CustomSequence(): def __len__(self): return 5 def __getitem__(self, index): return "x{0}".format(index)class FunkyBackwards(CustomSequence): def __reversed__(self): return "BACKWARDS!"for seq in normal_list, CustomSequence(), FunkyBackwards(): print("n{}: ".format(seq.__class__.__name__), end="") for item in reversed(seq): print(item, end=", ") The for loops at the end print the reversed versions of a normal list, and instances of the two custom sequences. The output shows that reversed works on all three of them, but has very different results when we define __reversed__ ourselves: list: 5, 4, 3, 2, 1,CustomSequence: x4, x3, x2, x1, x0,FunkyBackwards: B, A, C, K, W, A, R, D, S, !, Note: the above two classes aren't very good sequences, as they don't define a proper version of __iter__ so a forward for loop over them will never end. Enumerate Sometimes when we're looping over an iterable object in a for loop, we want access to the index (the current position in the list) of the current item being processed. The for loop doesn't provide us with indexes, but the enumerate function gives us something better: it creates a list of tuples, where the first object in each tuple is the index and the second is the original item. This is useful if we want to use index numbers directly. Consider some simple code that outputs all the lines in a file with line numbers: import sysfilename = sys.argv[1]with open(filename) as file: for index, line in enumerate(file): print("{0}: {1}".format(index+1, line), end='') Running this code on itself as the input file shows how it works: 1: import sys2: filename = sys.argv[1]3:4: with open(filename) as file:5: for index, line in enumerate(file):6: print("{0}: {1}".format(index+1, line), end='') The enumerate function returns a list of tuples, our for loop splits each tuple into two values, and the print statement formats them together. It adds one to the index for each line number, since enumerate, like all sequences is zero based. Zip The zip function is one of the least object-oriented functions in Python's collection. It takes two or more sequences and creates a new sequence of tuples. Each tuple contains one element from each list. This is easily explained by an example; let's look at parsing a text file. Text data is often stored in tab-delimited format, with a "header" row as the first line in the file, and each line below it describing data for a unique record. A simple contact list in tab-delimited format might look like this: first last emailjohn smith jsmith@example.comjane doan janed@example.comdavid neilson dn@example.com A simple parser for this file can use zip to create lists of tuples that map headers to values. These lists can be used to create a dictionary, a much easier object to work with in Python than a file! import sysfilename = sys.argv[1]contacts = []with open(filename) as file: header = file.readline().strip().split('t') for line in file: line = line.strip().split('t') contact_map = zip(header, line) contacts.append(dict(contact_map))for contact in contacts: print("email: {email} -- {last}, {first}".format( **contact)) What's actually happening here? First we open the file, whose name is provided on the command line, and read the first line. We strip the trailing newline, and split what's left into a list of three elements. We pass 't' into the strip method to indicate that the string should be split at tab characters. The resulting header list looks like ["first", "last", "email"]. Next, we loop over the remaining lines in the file (after the header). We split each line into three elements. Then, we use zip to create a sequence of tuples for each line. The first sequence would look like [("first", "john"), ("last", "smith"), ("email", "jsmith@example.com")]. Pay attention to what zip is doing. The first list contains headers; the second contains values. The zip function created a tuple of header/value pairs for each matchup. The dict constructor takes the list of tuples, and maps the first element to a key and the second to a value to create a dictionary. The result is added to a list. At this point, we are free to use dictionaries to do all sorts of contact-related activities. For testing, we simply loop over the contacts and output them in a different format. The format line, as usual, takes variable arguments and keyword arguments. The use of **contact automatically converts the dictionary to a bunch of keyword arguments (we'll understand this syntax before the end of the chapter) Here's the output: email: jsmith@example.com -- smith, johnemail: janed@example.com -- doan, janeemail: dn@example.com -- neilson, david If we provide zip with lists of different lengths, it will stop at the end of the shortest list. There aren't many useful applications of this feature, but zip will not raise an exception if that is the case. We can always check the list lengths and add empty values to the shorter list, if necessary. The zip function is actually the inverse of itself. It can take multiple sequences and combine them into a single sequence of tuples. Because tuples are also sequences, we can "unzip" a zipped list of tuples by zipping it again. Huh? Have a look at this example: >>> list_one = ['a', 'b', 'c']>>> list_two = [1, 2, 3]>>> zipped = zip(list_one, list_two)>>> zipped = list(zipped)>>> zipped[('a', 1), ('b', 2), ('c', 3)]>>> unzipped = zip(*zipped)>>> list(unzipped)[('a', 'b', 'c'), (1, 2, 3)] First we zip the two lists and convert the result into a list of tuples. We can then use parameter unpacking to pass these individual sequences as arguments to the zip function. zip matches the first value in each tuple into one sequence and the second value into a second sequence; the result is the same two sequences we started with! Other functions Another key function is sorted(), which takes an iterable as input, and returns a list of the items in sorted order. It is very similar to the sort() method on lists, the difference being that it works on all iterables, not just lists. Like list.sort, sorted accepts a key argument that allows us to provide a function to return a sort value for each input. It can also accept a reverse argument. Three more functions that operate on sequences are min, max, and sum. These each take a sequence as input, and return the minimum or maximum value, or the sum of all values in the sequence. Naturally, sum only works if all values in the sequence are numbers. The max and min functions use the same kind of comparison mechanism as sorted and list.sort, and allow us to define a similar key function. For example, the following code uses enumerate, max, and min to return the indices of the values in a list with the maximum and minimum value: def min_max_indexes(seq): minimum = min(enumerate(seq), key=lambda s: s[1]) maximum = max(enumerate(seq), key=lambda s: s[1]) return minimum[0], maximum[0] The enumerate call converts the sequence into (index, item) tuples. The lambda function passed in as a key tells the function to search the second item in each tuple (the original item). The minimum and maximum variables are then set to the appropriate tuples returned by enumerate. The return statement takes the first value (the index from enumerate) of each tuple and returns the pair. The following interactive session shows how the returned values are, indeed, the indices of the minimum and maximum values: >>> alist = [5,0,1,4,6,3]>>> min_max_indexes(alist)(1, 4)>>> alist[1], alist[4](0, 6) We've only touched on a few of the more important Python built-in functions. There are numerous others in the standard library, including: all and any, which accept an iterable and returns True if all, or any, of the items evaluate to true (that is a non-empty string or list, a non-zero number, an object that is not None, or the literal True). eval, exec, and compile, which execute string as code inside the interpreter. hasattr, getattr, setattr, and delattr, which allow attributes on an object to be manipulated as string names. And many more! See the interpreter help documentation for each of the functions listed in dir(__builtins__). Summary In this article we took a look at many useful built-in functions. Further resources on this subject: Python Graphics: Animation Principles [Article] Animating Graphic Objects using Python [Article] Python 3: When to Use Object-oriented Programming [Article] Objects in Python [Article]
Read more
  • 0
  • 0
  • 6485

article-image-getting-and-running-mysql-python
Packt
24 Dec 2010
8 min read
Save for later

Getting Up and Running with MySQL for Python

Packt
24 Dec 2010
8 min read
  MySQL for Python Integrate the flexibility of Python and the power of MySQL to boost the productivity of your Python applications Implement the outstanding features of Python's MySQL library to their full potential See how to make MySQL take the processing burden from your programs Learn how to employ Python with MySQL to power your websites and desktop applications Apply your knowledge of MySQL and Python to real-world problems instead of hypothetical scenarios A manual packed with step-by-step exercises to integrate your Python applications with the MySQL database server Getting MySQL for Python How you get MySQL for Python depends on your operating system and the level of authorization you have on it. In the following subsections, we walk through the common operating systems and see how to get MySQL for Python on each. Using a package manager (only on Linux) Package managers are used regularly on Linux, but none come by default with Macintosh and Windows installations. So users of those systems can skip this section. A package manager takes care of downloading, unpacking, installing, and configuring new software for you. In order to use one to install software on your Linux installation, you will need administrative privileges. Administrative privileges on a Linux system can be obtained legitimately in one of the following three ways: Log into the system as the root user (not recommended) Switch user to the root user using su Use sudo to execute a single command as the root user The first two require knowledge of the root user's password. Logging into a system directly as the root user is not recommended due to the fact that there is no indication in the system logs as to who used the root account. Logging in as a normal user and then switching to root using su is better because it keeps an account of who did what on the machine and when. Either way, if you access the root account, you must be very careful because small mistakes can have major consequences. Unlike other operating systems, Linux assumes that you know what you are doing if you access the root account and will not stop you from going so far as deleting every file on the hard drive. Unless you are familiar with Linux system administration, it is far better, safer, and more secure to prefix the sudo command to the package manager call. This will give you the benefit of restricting use of administrator-level authority to a single command. The chances of catastrophic mistakes are therefore mitigated to a great degree. More information on any of these commands is available by prefacing either man or info before any of the preceding commands (su, sudo). Which package manager you use depends on which of the two mainstream package management systems your distribution uses. Users of RedHat or Fedora, SUSE, or Mandriva will use the RPM Package Manager (RPM) system. Users of Debian, Ubuntu, and other Debian-derivatives will use the apt suite of tools available for Debian installations. Each package is discussed in the following: Using RPMs and yum If you use SUSE, RedHat, or Fedora, the operating system comes with the yum package manager . You can see if MySQLdb is known to the system by running a search (here using sudo): sudo yum search mysqldb If yum returns a hit, you can then install MySQL for Python with the following command: sudo yum install mysqldb Using RPMs and urpm If you use Mandriva, you will need to use the urpm package manager in a similar fashion. To search use urpmq: sudo urpmq mysqldb And to install use urpmi: sudo urpmi mysqldb Using apt tools on Debian-like systems Whether you run a version of Ubuntu, Xandros, or Debian, you will have access to aptitude, the default Debian package manager. Using sudo we can search for MySQLdb in the apt sources using the following command: sudo aptitude search mysqldb On most Debian-based distributions, MySQL for Python is listed as python-mysqldb. Once you have found how apt references MySQL for Python, you can install it using the following code: sudo aptitude install python-mysqldb Using a package manager automates the entire process so you can move to the section Importing MySQL for Python. Using an installer for Windows Windows users will need to use the older 1.2.2 version of MySQL for Python. Using a web browser, go to the following link: http://sourceforge.net/projects/mysql-python/files/ This page offers a listing of all available files for all platforms. At the end of the file listing, find mysql-python and click on it. The listing will unfold to show folders containing versions of MySQL for Python back to 0.9.1. The version we want is 1.2.2. Windows binaries do not currently exist for the 1.2.3 version of MySQL for Python. To get them, you would need to install a C compiler on your Windows installation and compile the binary from source. Click on 1.2.2 and unfold the file listing. As you will see, the Windows binaries are differentiated by Python version—both 2.4 and 2.5 are supported. Choose the one that matches your Python installation and download it. Note that all available binaries are for 32-bit Windows installations, not 64-bit. After downloading the binary, installation is a simple matter of double-clicking the installation EXE file and following the dialogue. Once the installation is complete, the module is ready for use. So go to the section Importing MySQL for Python. Using an egg file One of the easiest ways to obtain MySQL for Python is as an egg file, and it is best to use one of those files if you can. Several advantages can be gained from working with egg files such as: They can include metadata about the package, including its dependencies They allow for the use of egg-aware software, a helpful level of abstraction Eggs can, technically, be placed on the Python executable path and used without unpacking They save the user from installing packages for which they do not have the appropriate version of software They are so portable that they can be used to extend the functionality of third-party applications Installing egg handling software One of the best known egg utilities—Easy Install, is available from the PEAK Developers' Center at http://peak.telecommunity.com/DevCenter/EasyInstall. How you install it depends on your operating system and whether you have package management software available. In the following section, we look at several ways to install Easy Install on the most common systems. Using a package manager (Linux) On Ubuntu you can try the following to install the easy_install tool (if not available already): shell> sudo aptitude install python-setuptools On RedHat or CentOS you can try using the yum package manager: shell> sudo yum install python-setuptools On Mandriva use urpmi: shell> sudo urpmi python-setuptools You must have administrator privileges to do the installations just mentioned. Without a package manager (Mac, Linux) If you do not have access to a Linux package manager, but nonetheless have a Unix variant as your operating system (for example, Mac OS X), you can install Python's setuptools manually. Go to: http://pypi.python.org/pypi/setuptools#files Download the relevant egg file for your Python version. When the file is downloaded, open a terminal and change to the download directory. From there you can run the egg file as a shell script. For Python 2.5, the command would look like this: sh setuptools-0.6c11-py2.5.egg This will install several files, but the most important one for our purposes is easy_install, usually located in /usr/bin. On Microsoft Windows On Windows, one can download the setuptools suite from the following URL: http://pypi.python.org/pypi/setuptools#files From the list located there, select the most appropriate Windows executable file. Once the download is completed, double-click the installation file and proceed through the dialogue. The installation process will set up several programs, but the one important for our purposes is easy_install.exe. Where this is located will differ by installation and may require using the search function from the Start Menu. On 64-bit Windows, for example, it may be in the Program Files (x86) directory. If in doubt, do a search. On Windows XP with Python 2.5, it is located here: C:Python25Scriptseasy_install.exe Note that you may need administrator privileges to perform this installation. Otherwise, you will need to install the software for your own use. Depending on the setup of your system, this may not always work. Installing software on Windows for your own use requires the following steps: Copy the setuptools installation file to your Desktop. Right-click on it and choose the runas option. Enter the name of the user who has enough rights to install it (presumably yourself) After the software has been installed, ensure that you know the location of the easy_install.exe file. You will need it to install MySQL for Python.
Read more
  • 0
  • 0
  • 3200

article-image-using-urls-access-nnmi-objects
Packt
24 Dec 2010
14 min read
Save for later

Using URLs to Access NNMi Objects

Packt
24 Dec 2010
14 min read
  HP Network Node Manager 9: Getting Started Manage your network effectively with NNMi Install, customize, and expand NNMi functionality by developing custom features Integrate NNMi with other management tools, such as HP SW Operations Manager, Network Automation, Cisco Works, Business Availability center, UCMDB, and many others Navigate between incidents and maps to reduce troubleshooting time Screenshots and step-by-step instructions to customize NNMi in the way you want Instructions in the book are valid for version 8 as well         Read more about this book       URLs that are listed in this section can be grouped into a few groups (refer to the preceding screenshot): Generic URLs. Workspace-related URLs. Form-related URLs. Menu item-related URLs. As an example, we can provide a quick access to menu items for our team. For example, building a smart-phone application that displays critical events and allows user to run ping, trace route, or other commands for faster troubleshooting (refer to the next diagram). The following section lists these URLs and provides tables of parameters, which can be used for building URLs. Note: If our NNMi is configured to use the https protocol, we need to modify our URLs in this article accordingly, as URLs here are provided for http access. Generic URLs Generic URLs that can be used for obtaining information about NNMi are: View launching URL: To launch the NNMi console, use the following URL:http://<server_name>:<port_number>/nnm/launch?cmd=showMain. If we are passing by using a username and password within the URL, we need to use the following syntax: http://<server_name>:<port_number>/nnm/launch?cmd=showMain&j_username=<account_name>&j_password=<account_password>. To confirm whether NNMi is running: The following URL should be used: http:/<serverName>:<portNumber>/nnm/launch?cmd=isRunning. Using this URL, we will receive a confirmation response on whether or not NNMi is running. Otherwise, a browser error message will be sent saying that the URL is unreachable. Workspace-related URLs This URL group is related to NNMi views. Here is a list of available URLs. Launching view The following table presents the required attributes and their values for launching views. Attributes Values Description Use following URL to show general view: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&objtype=<x> objtype Incident Node Interface IP Address IP Subnet NodeGroup InterfaceGroup Incidents workspace, All Incidents table view. Inventory workspace, Nodes table view. Inventory workspace, Interfaces table view. Inventory workspace, IP Addresses table view. Inventory workspace, IP Subnets table view. Inventory workspace, Node Groups table view. Inventory workspace, Interface Groups table view. Use the following URL to show general view for a specific node group, filtered by node group name, id, or uuid: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&objtype= <x>&nodegroup=<Name> nodegroup nodegroup nodegroupid     nodegroupuuid The Name attribute value of Node Group*. The ID number of node group. This ID is unique across all NNMi database. Use nnmconfigexport.ovpl tool to see ID number of node group. Universally Unique Object ID of the node group. Use nnmconfigexport.ovpl tool to see ID number of node group. Use following URL to show general view for a specific node group, filtered by interface group name or id: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&objtype=<x>&ifgroup=<Name> ifgroup ifgroup ifgroupid     ifgroupduuid The name attribute value of interface group*. The ID number of interface group. This ID is unique across all NNMi database. Use nnmconfigexport.ovpl tool to see id number of interface group. Universally Unique Object ID of the interface group. Use nnmconfigexport.ovpl tool to see id number of interface group. Use following URL to show general view with custom window settings: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&objtype=<x>&menus=<true|false>&newWindow=<true|false>&envattrs=<name1=value>;<name2=value> menus [true|false] True: Show the view menus. False: Hide the view menus. The default value is true. newWindow [true|false] True: To display view in new window. False: To display view within same browser window. Default value is false. envattrs   This is session-specific attributes and they are stored by following syntax: <name=value>.     * If the node group name has spaces in it, use one of the following symbols to represent a "space" character (without brackets): "%20", "+", or " " (space symbol). Consider the following example. To open a window with incidents, which are related to the node group Europe, run the following URL (assuming, that NNMi is installed on node "box1" and uses port number "8080"): http://box1:8080/nnm/launch?cmd=showView&objtype=Incident&nodegroup=Europe Launching an Incident view The following table presents the required attributes and their values for launching incident-specific views. Attributes Values Description Use following URL to show incident view, filtered by specific incident attributes: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x> view allIncidentsTableView allOpenIncidentsTableView closedKeyIncidentsTableView closedRCIncidentTableView customIncidentTableView incidentsByNatureTableView incidentsByFamilyTableView keyIncidentsByLifecycleStateTableView myIncidentTableView nnm6x7xIncidentTableView nnm6x7xIncidentByCategoryTableView openKeyIncidentsTableView openKeyIncidentsByCategoryTableView openKeyIncidentsByFamilyTableView openKeyIncidentsByPriorityTableView openKeyIncidentsBySeverityTableView openRCIncidentsByCategoryTableView openRCIncidentsByFamilyTableView openRCIncidentsByPriorityTableView openRCIncidentsBySeverityTableView openRCIncidentTableView allRCIncidentTableView RCIncidentsByLifecycleStateTableView serviceImpactIncidentTableView snmpTrapsIncidentTableView snmpTrapsIncidentByFamilyTableView streamCorrelationIncidentTableView unassignedKeyIncidentsTableView unassignedIncidentTableView All incidents All open incidents Closed Key Incidents Closed Root Cause Incidents Custom Incidents Incidents by Correlation Nature Incidents by Family Key Incidents by Lifecycle State My Open Incidents NNM 6.x / 7.x Events NNM 6.x/7.x Event by Category Open Key Incidents Open Key Incidents by Category Open Key Incidents by Family Open Key Incidents by Priority Open Key Incidents by Severity Open Root Cause by Category Open Root Cause by Family Open Root Cause by Priority Open Root Cause by Severity Open Root Cause Incidents Root Cause Incidents Root Cause by Lifecycle State Service Impact Incidents SNMP Traps SNMP Traps by Family Stream Correlation Incidents Unassigned Open Key Incidents Unassigned Root Cause Incidents Use following URL to show Incident view, filtered for specific node group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&nodegroup_var=<Name> See the preceding table for attribute description. Use following URL to show Incident view with custom window settings: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&menus_var=<true|false>&newWindow=<true|false>&envattrs=<name1=value>;<name2=value> See the preceding table for attribute description.   Launching a Topology Maps Workspace view Here is a list of Topology Maps that can be opened using the following URLs: Consider the following example. Here are the links to open a few groups on NNMi server "box1" (port number 8080): Open Routers node groups: http://box1:8080/nnm/launch?cmd=showNodeGroup&name=Routers Open Networking Infrastructure devices: http://box1:8080/nnm/launch?cmd=showView&objtype= Node&nodegroup=Networking%20Infrastructure%20Devices Launching a Monitoring Workspace view The following table presents the required attributes and their values for launching Monitoring workspace-specific views. Attributes Values Description Use following URL to show monitoring view, filtered by specific attributes: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x> view criticalComponentHealthTableView criticalInterfaceTableView criticalNodeTableView nonNormalInterfaceTableView nonNormalNodeTableView notRespondingIPAddressTableView nodesByStatusTableView componentHealthByStatusTableView interfacesByStatusTableView interfacesByAdministrativeStateTableView interfacesByOperationalStateTableView IPAddressesByStateTableView interfacePerformanceTableView routerRedundancyGroupsTableView nodeGroupsStatusTableView Critical Component Health Critical Interfaces Critical Nodes Non-Normal Interfaces Non-Normal Nodes Not Responding Addresses Nodes by Status Component Health by Status Interfaces by Status Interfaces by Administrative State Interfaces by Operational State IP Addresses by State Interface Performance Router Redundancy Groups Node Groups Use following URL to show monitoring view, filtered by node group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&nodegroup=<Name> Refer to the table under the Launching view section for attribute description. Use following URL to show general view, filtered by interface group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&ifgroup=<Name> Refer to the table under the Launching view section for attribute description. Use following URL to show monitoring view with custom window settings: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&menus=<true|false>&newWindow=<true|false>&envattrs=<name1=value>;<name2=value> Refer to the table under the Launching view section for attribute description.   Launching a Troubleshooting Workspace view Troubleshooting workspace contains the following four different views: Layer 2 Neighbor view Layer 3 Neighbor view Path view Node Group Map view Use the following URL to show the Layer 2 Neighbor view: http://<serverName>:<portNumber>/nnm/launch?cmd=showLayer2Neighbors. Attributes   Values Description Use following URL to show Layer 2 Neighbor view by specified number of hops: http://<serverName>:<portNumber>/nnm/launch?cmd=showLayer2Neighbors&nodename=<x>&hops=<#> nodename nodename The source node's name or IP address hops 1 - 9 Number of hops Use following URL to show Layer 2 Neighbor view with custom window parameters: http://<serverName>:<portNumber>/nnm/launch?cmd=showLayer2Neighbors&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value> Refer to the table under the Launching view section for attribute description.   Use the following URL to show Layer 3 Neighbor view: http://<serverName>:<portNumber>/nnm/launch?cmd= showLayer3Neighbors. Attributes Values Description Use following URL to show Layer 3 Neighbor view for specified node by specified number of hops: http://<serverName>:<portNumber>/nnm/launch?cmd=showLayer3Neighbors&nodename=<x>&hops=<#> nodename See the previous table for attribute description. hops See the previous table for attribute description. menus [true|false] Show (true) or hide (false) menu and window toolbar. Default value is "true".   Use the following URL to show Layer 3 Neighbor view with the specified window parameters: http://<serverName>:<portNumber>/nnm/launch?cmd=showLayer3Neighbors&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value>. Use the following URL to show Path view: http://<serverName>:<portNumber>/nnm/launch?cmd=showPath. Attributes Values Description Use the following URL to show Path view by specified source and destination nodes: http://<serverName>:<portNumber>/nnm/launch?cmd=showPath&src=<x>&dest=<y> src src Source node's hostname or IPv4 address. dest dest Destination node's hostname or IPv4 address. Use the following URL to show Path view with custom window parameters: http://<serverName>:<portNumber>/nnm/launch?cmd=showPath&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2= value> Attributes Values Description   Use following URL to list nodes belonging to a specified node group: http://<serverName>:<portNumber>/nnm/launch?cmd=showNodeGroup&name=<x> name name The Name attribute value from the Node Group form   Use the following URL to list nodes belonging to a specified node group with custom window parameters: http://<serverName>:<portNumber>/nnm/launch?cmd=showNodeGroup&name=<x>&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value>. Launching an Inventory Workspace view The following table presents the required attributes and their values for launching Inventory workspace-specific views. Attributes Values Description Use the following URL to show a view, specified in the view list below in this table: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x> view allNodesTableView allInterfacesTableView allIPAddressTableView allIPSubnetsTableView allVlansTableView allLayer2ConnectionsTableView nodesByDeviceCategoryTableView interfacesByIfTypeTableView customNodeTableView customInterfaceTableView customIPAddressTableView routerRedundancyGroupsTableView nodeGroupsTableView interfaceGroupsTableView allManagementStationsTableView Nodes Interfaces IP Addresses IP Subnets VLANs Layer 2 Connections Nodes by Device Category Interfaces by IfType Custom Nodes Custom Interfaces Custom IP Addresses Router Redundancy Groups Node Groups Interface Groups Management Stations Use the following URL to show a view, specified in the view list below in this table for specified node group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&nodegroup=<Name>. Refer to the table under the Launching view section for attribute description. nodegroup nodegroup nodegroupid nodegroupuuid Refer to the table under the Launching view section for attribute description. Use the following URL to show a view, specified in the view list below in this table for specified interface group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&interfacegroup=<Name> interfacegroup ifgroup ifgroupid ifgroupuuid Refer to the table under the Launching view section for attribute description.   Use the following URL to show a view, specified in the view list above in a table with custom window settings: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&menus= <true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value>. Launching Management Mode Workspace views The following table presents the required attributes and their values for launching Management Mode workspace-specific views: Attributes Values Description Use the following URL to show a view, specified in the view list below in this table: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x> view allNodesTableView allInterfacesTableView allIPAddressTableView allIPSubnetsTableView allVlansTableView allLayer2ConnectionsTableView nodesByDeviceCategoryTableView interfacesByIfTypeTableView customNodeTableView customInterfaceTableView customIPAddressTableView routerRedundancyGroupsTableView nodeGroupsTableView interfaceGroupsTableView allManagementStationsTableView Nodes Interfaces IP Addresses IP Subnets VLANs Layer 2 Connections Nodes by Device Category Interfaces by IfType Custom Nodes Custom Interfaces Custom IP Addresses Router Redundancy Groups Node Groups Interface Groups Management Stations Use the following URL to show a view, specified in the view list below in this table for specified node group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&nodegroup=<Name>. Refer to the table under the Launching view section for attribute description. nodegroup nodegroup nodegroupid nodegroupuuid Refer to the table under the Launching view section for attribute description. Use the following URL to show a view, specified in the view list below in this table for specified interface group: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view= <x>&interfacegroup=<Name> interfacegroup ifgroup ifgroupid ifgroupuuid Refer to the table under the Launching view section for attribute description. Use the following URL to show a view, from the Management Mode workspace, with specified window settings: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value>. Launching a Configuration Workspace view The following table presents the required attributes and their values for launching the Configuration workspace-specific views: Attributes Values Description Use the following URL to show a view from Configuration workspace for a view specified below: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>. view nodeGroupsTableView allNodeGroupMapSettingsTableView interfaceGroupsTableView allManagementStationsTableView ramsServerTableView allURLActionInfosTableView allAccountsTableView allIfTypesTableView allDeviceProfilesTableView Node Groups Node Group Map Settings Interface Groups Management Stations RAMS Servers URL Actions User Accounts and Roles IfTypes Device Profiles   Use the following URL to show a view, from Configuration workspace, with specified window parameters: http://<serverName>:<portNumber>/nnm/launch?cmd=showView&view=<x>&menus=<true/false>&newWindow=<true/false>&envattrs=<name1=value>;<name2=value>.  
Read more
  • 0
  • 0
  • 14016
article-image-tips-tricks-mysql-python
Packt
23 Dec 2010
5 min read
Save for later

Tips & Tricks on MySQL for Python

Packt
23 Dec 2010
5 min read
  MySQL for Python Integrate the flexibility of Python and the power of MySQL to boost the productivity of your Python applications Implement the outstanding features of Python's MySQL library to their full potential See how to make MySQL take the processing burden from your programs Learn how to employ Python with MySQL to power your websites and desktop applications Apply your knowledge of MySQL and Python to real-world problems instead of hypothetical scenarios A manual packed with step-by-step exercises to integrate your Python applications with the MySQL database server         Read more about this book       (For more resources on this subject, see here.) Objective: Install a C compiler on Windows installation. Tip: Windows binaries do not currently exist for the 1.2.3 version of MySQL for Python. To get them, you would need to install a C compiler on your Windows installation and compile the binary from source. Objective: Use tar.gz to use egg file. Tip: If you cannot use egg files or if you use an earlier version of Python, you should use the tar.gz file, a tar and gzip archive. The tar.gz archive follows the Linux egg files in the file listing. The current version of MySQL for Python is 1.2.3c1, so the file we want is as following: MySQL-python-1.2.3c1.tar.gz This method is by far more complicated than the others. If at all possible, use your operating system's installation method or an egg file. Objective: Limitation of using MySQL for Python on Python version. Tip: This version of MySQL for Python is compatible up to Python 2.6. It is worth noting that MySQL for Python has not yet been released for Python 3.0 or later versions. In your deployment of the library, therefore, ensure that you are running Python 2.6 or earlier. As noted, Python 2.5 and 2.6 have version-specifi c releases. Prior to Python 2.4, you will need to use either a tar.gz version of the latest release or use an older version of MySQL for Python. The latter option is not recommended. Objective: It is important to phrase the query in such a way as to narrow the returned values as much as possible. Tip: Here, instead of returning whole records, we tell MySQL to return only the namecolumn. This natural reduction in the data reduces processing time for both MySQL and Python. This saving is then passed on to your server in the form of more sessions able to be run at one time. Objective: This hard-wiring of the search query allows us to test the connection before coding the rest of the function. Tip: There may be a tendency here to insert user-determined variables immediately. With experience, it is possible to do this. However, if there are any doubts about the availability of the database, your best fallback position is to keep it simple and hardwired. This reduces the number of variables in making a connection and helps one to blackbox the situation, making troubleshooting much easier. Objective: Readability counts. Tip: The virtue of readability in programming is often couched in terms of being kind to the next developer who works on your code. There is more at stake, however. With readability comes not only maintainability but control. If it takes you too much effort to understand the code you have written, you will have a harder time controlling the program's flow and this will result in unintended behavior. The natural consequence of unintended program behavior is the compromising of process stability and system security. Objective: Quote marks not necessary when assigning MySQL statements. Tip: It is not necessary to use triple quote marks when assigning the MySQL sentence to statement or when passing it to execute(). However, if you used only a single pair of either double or single quotes, it would be necessary to escape every similar quote mark. As a stylistic rule, it is typically best to switch to verbatim mode with the triple quote marks in order to ensure the readability of your code. Objective: xrange() is much more memory efficient than range(). Tip: The differences between xrange() and range() are often overlooked or even ignored. Both count through the same values, but they do it differently. Where range() calculates a list the first time it is called and then stores it in memory, xrange() creates an immutable sequence that returns the next in the series each time it is called. As a consequence, xrange() is much more memory efficient than range(), especially when dealing with large groups of integers. As a consequence of its memory efficiency, however, it does not support functionality such as slicing, which range() does, because the series is not yet fully determined. Objective: autocommit feature is useful in MySQL for Python . Tip: Unless you are running several database threads at a time or have to deal with similar complexity, MySQL for Python does not require you to use either commit() or close(). Generally speaking, MySQL for Python installs with an autocommit feature switched on. It thus takes care of committing the changes for you when the cursor object is destroyed. Similarly, when the program terminates, Python tends to close the cursor and database connection as it destroys both objects.
Read more
  • 0
  • 0
  • 5412

article-image-working-xml-documents-php-jquery
Packt
23 Dec 2010
8 min read
Save for later

Working with XML Documents in PHP jQuery

Packt
23 Dec 2010
8 min read
PHP jQuery Cookbook Over 60 simple but highly effective recipes to create interactive web applications using PHP with jQuery Create rich and interactive web applications with PHP and jQuery Debug and execute jQuery code on a live site Design interactive forms and menus Another title in the Packt Cookbook range, which will help you get to grips with PHP as well as jQuery Introduction Extensible Markup Language—also known as XML—is a structure for representation of data in human readable format. Contrary to its name, it's actually not a language but a markup which focuses on data and its structure. XML is a lot like HTML in syntax except that where HTML is used for presentation of data, XML is used for storing and data interchange. Moreover, all the tags in an XML are user-defined and can be formatted according to one's will. But an XML must follow the specification recommended by W3C. With a large increase in distributed applications over the internet, XML is the most widely used method of data interchange between applications. Web services use XML to carry and exchange data between applications. Since XML is platform-independent and is stored in string format, applications using different server-side technologies can communicate with each other using XML. Consider the following XML document: From the above document, we can infer that it is a list of websites containing data about the name, URL, and some information about each website. PHP has several classes and functions available for working with XML documents. You can read, write, modify, and query documents easily using these functions. In this article, we will discuss SimpleXML functions and DOMDocument class of PHP for manipulating XML documents. You will learn how to read and modify XML files, using SimpleXML as well as DOM API. We will also explore the XPath method, which makes traversing documents a lot easier. Note that an XML must be well-formed and valid before we can do anything with it. There are many rules that define well-formedness of XML out of which a few are given below: An XML document must have a single root element.   There cannot be special characters like <, >, and soon.   Each XML tag must have a corresponding closing tag.   Tags are case sensitive To know more about validity of an XML, you can refer to this link: http://en.wikipedia.org/wiki/XML#Schemas_and_validation For most of the recipes in this article, we will use an already created XML file. Create a new file, save it as common.xml in the Article3 directory. Put the following contents in this file. <?xml version="1.0"?> <books> <book index="1"> <name year="1892">The Adventures of Sherlock Holmes</name> <story> <title>A Scandal in Bohemia</title> <quote>You see, but you do not observe. The distinction is clear.</quote> </story> <story> <title>The Red-headed League</title> <quote>It is quite a three pipe problem, and I beg that you won't speak to me for fifty minutes.</quote> </story> <story> <title>The Man with the Twisted Lip</title> <quote>It is, of course, a trifle, but there is nothing so important as trifles.</quote> </story> </book> <book index="2"> <name year="1927">The Case-book of Sherlock Holmes</name> <story> <title>The Adventure of the Three Gables</title> <quote>I am not the law, but I represent justice so far as my feeble powers go.</quote> </story> <story> <title>The Problem of Thor Bridge</title> <quote>We must look for consistency. Where there is a want of it we must suspect deception.</quote> </story> <story> <title>The Adventure of Shoscombe Old Place</title> <quote>Dogs don't make mistakes.</quote> </story> </book> <book index="3"> <name year="1893">The Memoirs of Sherlock Holmes</name> <story> <title>The Yellow Face</title> <quote>Any truth is better than indefinite doubt.</quote> </story> <story> <title>The Stockbroker's Clerk</title> <quote>Results without causes are much more impressive. </quote> </story> <story> <title>The Final Problem</title> <quote>If I were assured of your eventual destruction I would, in the interests of the public, cheerfully accept my own.</quote> </story> </book> </books> Loading XML from files and strings using SimpleXML True to its name, SimpleXML functions provide an easy way to access data from XML documents. XML files or strings can be converted into objects, and data can be read from them. We will see how to load an XML from a file or string using SimpleXML functions. You will also learn how to handle errors in XML documents. Getting ready Create a new directory named Article3. This article will contain sub-folders for each recipe. So, create another folder named Recipe1 inside it. How to do it... Create a file named index.php in Recipe1 folder. In this file, write the PHP code that will try to load the common.xml file. On loading it successfully, it will display a list of book names. We have also used the libxml functions that will detect any error and will show its detailed description on the screen. <?php libxml_use_internal_errors(true); $objXML = simplexml_load_file('../common.xml'); if (!$objXML) { $errors = libxml_get_errors(); foreach($errors as $error) { echo $error->message,'<br/>'; } } else { foreach($objXML->book as $book) { echo $book->name.'<br/>'; } } ?> Open your browser and point it to the index.php file. Because we have already validated the XML file, you will see the following output on the screen: The Adventures of Sherlock Holmes The Case-book of Sherlock Holmes The Memoirs of Sherlock Holmes Let us corrupt the XML file now. For this, open the common.xml file and delete any node name. Save this file and reload index.php on your browser. You will see a detailed error description on your screen: How it works... In the first line, passing a true value to the libxml_use_internal_errors function will suppress any XML errors and will allow us to handle errors from the code itself. The second line tries to load the specified XML using the simplexml_load_file function. If the XML is loaded successfully, it is converted into a SimpleXMLElement object otherwise a false value is returned. We then check for the return value. If it is false, we use the libxml_get_errors() function to get all the errors in the form of an array. This array contains objects of type LibXMLError. Each of these objects has several properties. In the previous code, we iterated over the errors array and echoed the message property of each object which contains a detailed error message. If there are no errors in XML, we get a SimpleXMLElement object which has all the XML data loaded in it. There's more... Parameters for simplexml_load_file More parameters are available for the simplexml_load_file method, which are as follows: filename: This is the first parameter that is mandatory. It can be a path to a local XML file or a URL. class_name: You can extend the SimpleXMLElement class. In that case, you can specify that class name here and it will return the object of that class. This parameter is optional. options: This third parameter allows you to specify libxml parameters for more control over how the XML is handled while loading. This is also optional. simplexml_load_string Similar to simplexml_load_file is simplexml_load_string, which also creates a SimpleXMLElement on successful execution. If a valid XML string is passed to it we get a SimpleXMLElement object or a false value otherwise. $objXML = simplexml_load_string('<?xml version="1.0"?><book><name> Myfavourite book</name></book>'); The above code will return a SimpleXMLElement object with data loaded from the XML string. The second and third parameters of this function are same as that of simplexml_load_file. Using SimpleXMLElement to create an object You can also use the constructor of the SimpleXMLElement class to create a new object. $objXML = new SimpleXMLElement('<?xml version="1.0"?><book><name> Myfavourite book</name></book>'); More info about SimpleXML and libxml You can read about SimpleXML in more detail on the PHP site at http://php.net/manual/en/book.simplexml.php and about libxml at http://php.net/manual/en/book.libxml.php.
Read more
  • 0
  • 0
  • 7120
Modal Close icon
Modal Close icon