Skip to content

Additional Functionality

robertkearns edited this page Jul 14, 2019 · 3 revisions

Different Search Types

searchtype='value':

In addition to searching via key; Aphid also supports searching instead with a value. Simply use the searchtype='value' in any command.

nest = nest = {1:{2:{'the obvious key':'the hidden value'}}}

result = Aphid.search(nest, 'the hidden value', searchtype='value')
>>>result
('the obvious key', 'the hidden value')

Using different types as the searchfor argument:

All calls are able to take more than just a string.

  • Using a Regular Expression:

    • Regular expressions can be passed as the searchfor argument. Simply compile a pattern and use the variable that holds reference.
       import re
       regex = re.compile(r'custom regex expression')
       Aphid.search(data, regex)
    • Comparisons are done using re.search() function. If it returns anything other than None, on_match is called
  • Using a List, Tuple:

    • A list or tuple can be utilized to find a match containing any element of the list/tuple. For example:
      Aphid.findall(data, ['one', 'two', 'three'])
      This will return any key that directly matches any of: 'one', 'two', 'three'. Most helpful when you have multiple ideas of what your desired data could be called internally.

Additional **kwargs:

  • max_depth=0:

    • Takes an int, if 0 no limit is applied. Aphid works based on recursion. This can cause issues if you are dealing with a big data set. Python itself limits the recursion depth to around 1000(system dependent). This is to prevent a stack overflow that would crash your program. Aphid allows you to define a max recursion level. For example in a data set that has 'key' nested 10 layers need, max_depth=9 would prevent this from being found. Limiting the max depth is an optimal way to speed up a search. If an attribute you seek is burried very deep and you are having trouble getting to it, try these steps:

      • If the search crashes:

        • Try limiting the max_depth and see if any results can be found.
        • Look for potential parents by calling YourClass.__dict__.keys()
          • If you can narrow your search field by finding potential parents; this will often be enough to find a match
          • For example if looking for the title of a chart in an excel object instead of searching the entire instance, we call the .keys() on the classes attributes.
            >>>excel_obj.__dict__.keys()
            ['cells', 'formatting', 'date', '_charts', 'formulas']
            >>>type(excel_obj._charts)
            <class 'list'>
            >>>len(excel_obj._charts)
            1
            >>>Aphid.search(excel_obj._charts[0], 'My chart title', searchtype='value', max_depth=100)
            [<Class Barchart>, <Class title obj>, <Class rich text>, text, paragraphs, <Class rich text>, t]
            Now we have successfully mapped the location, instead of crashing the interpreter with a massive data set.
  • debug=False:

Subclassing

Aphid is run on classes behind the scenes. Each function has its own class. For example Aphid.search() actually instantiates an instance of Aphid.Objects.Search(). Each class inherits the majority of its functionality from the Aphid.Objects.BaseMethods. Defined there is a preemptive __init__ which assigns attributes common to each class and makes sure the right methods are put in reference based on the users call parameters.

Unique to each method is an on_match method; each class defines their own. By subclassing the on_match method tons of functionality can be added to the call.

on_match(self, key, value, iterable):

*Note: depending on the class making the call to on_match, iterable is either the parent of the match or is the path to it. Both FindPaths() and FindClassPaths() pass a path as the fourth argument, while all others pass the parent iterable.

This example will take a response with ISO datetags and replace each one with a datetime object.

chain = {'optionChain': [{'expiryDate': '2019-07-19T00:00:00.000000-04:00', 'description': 'BANK OF MONTREAL'},
          {'expiryDate': '2019-07-26T00:00:00.000000-04:00', 'description': 'BANK OF MONTREAL'}]}
from Aphid.objects import Findall
import ISO

class ReplaceDates(Findall):
    def on_match(self, key, value, iterable):
        iterable[key] = ISO.ISOtdatetime(value)

ReplaceDates(chain, 'expiryDate')
>>>chain
{'optionChain': [{'expiryDate': datetime.datetime(2019, 7, 19, 0, 0), 'description': 'BANK OF MONTREAL'},
 {'expiryDate': datetime.datetime(2019, 7, 26, 0, 0), 'description': 'BANK OF MONTREAL'}]}