Skip to content
sggottlieb edited this page Apr 23, 2012 · 3 revisions

How to write a signature

A signature is a class that provides information about the platform and tests for determining if the platform is running the site. The detector framework does the heavy lifting of interacting with the site and running the tests. By using the framework you can:

  • Look for a pattern in a page
  • Check the existence of a URL

If you need other tools, let us know and we will work with you to add them to the framework.

The best way to explain how to write a signature is to show it. What follows is a walk through of a basic signature.

First, here is the full code. Feel free to copy/paste this as a template.

"""
This signature containts test to see if the site is running on Umbraco.
"""
__author__ = "Seth Gottlieb"
__copyright__ = "CM Fieldguide"
__credits__ = ["Seth Gottlieb",]
__license__ = "Unlicense"
__version__ = "0.1"
__maintainer__ = "Seth Gottlieb"
__email__ = "[email protected]"
__status__ = "Experimental"


from cmfieldguide.cmsdetector.signatures import BaseSignature, get_url_stem


class Signature(BaseSignature):

    NAME = 'Umbraco'
    WEBSITE = 'http://umbraco.com/'
    KNOWN_POSITIVE = 'http://umbraco.com/'
    TECHNOLOGY = '.NET'

    def test_has_umbraco_login(self, site):
        """
        Umbraco sites have a login page under the URL '/umbraco/login.aspx'.

        """
    
        if site.page_cache[site.url_stem + '/umbraco/login.aspx'].contains_pattern('<input name="lname"'):
           return 1
        else:
           return 0

##The Header

  • __author__: Put your name here
  • __copyright__: If this is your contribution, go ahead put your name here
  • __credits__: If you enhance this, feel free to add your name to the list
  • __license__: We are using the "Unlicense" for this code to make it public domain
  • __maintainer__: This would be you

##Class Metadata

  • NAME: This name of the platform that is listed on the result list.
  • WEBSITE: This is the website of the platform supplier
  • KNOWN_POSITIVE: This is a site that you know is running on the platform
  • TECHNOLOGY: Could be .NET, BAKED, JAVA, PHP or anything else. We have some additional checks like we eliminate your .NET platform as a possibility if the site is running on PHP.

##A Test

def test_has_umbraco_login(self, url):

To be run by the test runner, a test method must begin with the string "test_". Your test should take the URL that the visitor entered. You an manipulate the URL to call other pages on the site. This code sample looks for a login page off the root.

##A DocString

"""
Umbraco sites have a login page under the URL '/umbraco/login.aspx'.
"""

The doc string is important here. We show this on the test result page. Your doc string should succinctly explain what the test is looking for.

##Test Logic

if site.page_cache[site.url_stem + '/umbraco/login.aspx'].contains_pattern('<input name="lname"'):

You will also notice that this code uses page_cache. This prevents all the different platform tests from calling the same page over and over again. Treat the page_cache like a dictionary. If the page_cache doesn't have your page in it, it will go out and retrieve it for you.

The Page object that comes back has a some data about the page and some methods to inspect it. This is the most basic example. It is looking for a string in the page using a "contains_pattern" method.

See the documentation for cmfieldguide.cmsdetector.signatures.Page for more information.

##The Result

A test should return one of the following values:

  • 1 is a positive result. You found what you were looking for.
  • 0 is a non-conclusive negative result. You didn't find what you were looking for but you still can't rule out the platform
  • -1 is a conclusive negative result. You know your platform is not running this site. We abort all subsequent tests when we encounter this result.

##Conclusion

So there you have it. In just a few lines of code, I was able to turn a trick I knew into a shared resource that we can all use.

Clone this wiki locally