Skip to main content

A library to query nested data in Python

Project description

pyspecter

Python version PyPI version PyPI download

A Python library to query nested structure, inspired by specter

If you are dealing with nested python structure and it require complex rule to search the data underneath like:

  • Key start with a pattern
  • Value to be filter
  • Conditional path to walk into
  • ...

this is the right library fit the use case as it extract the Navigation rule to a list, saving your a lot of trouble writting your own logic to navigate the nested data.

Get started

image

Examples

m = {"A":{"B1":[10,20],"B2":2,"B3":3}
     ,"C":{"B1":[1,2],"B2":[3,4]}
     ,"D":[1,2,3,4]
     ,"E":[None,2,3,4]
     ,"F":{"G":1}
     ,"H":["A1","A2","A3"]}

Navigate to specific item

FIRST/LAST

assert query(m, ["D", S.FIRST]) == 1
assert query(m, ["A", S.FIRST]) == ("B1", [10, 20]) # first element from dict.items()

assert query(m, ["D", S.LAST]) == 4
assert query(m, ["A", S.LAST]) == ("B3", 3) # last element from dict.items()

Nth

Navigate to the Nth element

assert query(m, ["D", (S.NTH, 1)]) == 2
assert query(m, ["D",(S.NTH, 1, 2)]) == [ 2, 3 ]

Operation on dict

Navigate to values or keys of current position

assert query(m, ["C", S.MVALS]) == [[1, 2], [3, 4]]
assert query(m, ["C", S.MKEYS]) == ['B1', 'B2']

Navigate to a sub map of current position

assert query(m, ["A", (S.SUB_MAP, "B1")]) == {"B1":[10,20]}

Annotate with index with current position

assert query(m, ["A", S.INDEXED_VALS]) == [(0, ("B1", [10,20])), (1, ("B2", 2)), (2, ("B3", 3))]
assert query(m, ["C", "B1", S.INDEXED_VALS]) == [(0, 1), (1, 2)]

Filtering

filter elements by supplying a function

assert query(m, ["A", "B1", (S.FILTER, lambda x: x > 10)]) == [20]
assert query(m, ["C", (S.FILTER, lambda k, v: k.endswith("2"))]) == [[3, 4]]

Navigate to map which its key or value satisify a custom function

assert query(m, ["A", (S.MKEY_IF, lambda x:x.endswith("1"))]) == [[10, 20]]
assert query(m, ["A", (S.MVAL_IF, lambda x:x==[10,20])]) == [[10, 20]]

Branching paths

Branching by multiple paths

mpath = {"A":{"B":1,
              "C":[2,3,4,5]}}
assert query(mpath,["A",
                    (S.MULTI_PATH,["B"]
                                 ,["C", S.LAST])]) == [1,5]

Conditional Navigation

Navigate to a specifie path

assert query(m, ["D", (S.NTH_PATH, 2)]) == [3]

Navigate to a position if and only if the path exists

assert query(m, [(S.MUST,"F","G")]) == 1
assert query(m, [(S.MUST,"F","G","NOT_EXISTS")]) == None 

Navigate to a range

assert query(m, ["D",(S.SRANGE,2,3)]) == [3]

Navigate to a 2nd path if 1st path exists, else return None

assert query(m,[(S.IF_PATH,["C","B1"],["E"])]) == [None,2,3,4]
assert query(m,[(S.IF_PATH,["C","B1"],["NOT_EXISTS"])]) == None

Navigate to a 2nd path if 1st path exists, else navigate to 3rd path

assert query(m,[(S.IF_PATH,["C","B3"],["E"],["F"])]) == {'G': 1}

Navigate to values of dict if key satisfy a regex expression:

assert query(m, ["A",(S.REGEX,r"B[23]")]) == [ 2,3 ]

Navigate to values of list if elements satisfy a regex expression:

assert query(m, ["H",(S.REGEX,r"\S1")]) == [ "A1" ]

Navigate with optional path node

assert query(m, [(S.MAYBE,"F","G")]) == 1

Handling None value

Return default value if current position is None

assert query(None,[(S.NONE_VAL,10)]) == 10

If current position is not a None,then return the value of current position

assert query(5,[(S.NONE_VAL,10)]) == 5

Operation on results

user can operate on the query result by

  • REUDCE -> perform reduce on the list or dict result ,from left to right.
m2 = {"A":{"B":["C1","C2","C3"]}}
assert query(m2, ["A","B",(H.REDUCE,lambda acc,x:acc+"|"+x, ">>>")]) == ">>>|C1|C2|C3"
assert query(m2, ["A","B",(H.REDUCE,lambda acc,x:acc+"|"+x)]) == "C1|C2|C3"

m2 = {"A":{"B":1,"D":2}}
assert query(m2, ["A",(H.REDUCE,lambda acc,x:acc+"|"+str(x[1]),">>")]) == ">>|1|2"
assert query(m2, ["A",(H.REDUCE,lambda acc,x:acc+"|"+str(x[0]),">>")]) == ">>|B|D"
  • MAP -> performn a transformation on the list or dict result
m2 = {"A":{"B":["C1","C2","C3"]}}
assert query(m2, ["A","B",(H.MAP,lambda x:x+"!")]) == ["C1!","C2!","C3!"]

m2 = {"A":{"B":"C1","D":"C2"}}
assert query(m2, ["A",(H.MAP,(lambda k,v: v+"!"))]) == ["C1!","C2!"]
  • SUM -> sum() the result list, with optional custom function passed before summing.
m2 = {"A":{"B":[1,2]}}
assert query(m2, ["A","B",H.SUM]) == 3

m2 = {"A":{"B":"1","D":"2"}}
assert query(m2, ["A",S.MVALS,(H.SUM,lambda x: int(x))]) == 3
  • MAX/MIN -> Using built-in max()/min() on the list result, with optioanl custom function passed before max/min
m2 = {"A":{"B":[3,5,2]}}
assert query(m2, ["A","B",H.MIN]) == 2
assert query(m2, ["A","B",(H.MIN,str)]) == "2"
assert query(m2, ["A","B",H.MAX]) == 5
assert query(m2, ["A","B",(H.MAX, str)]) == "5"
  • ORDER -> using sorted() to sort the result list, with optional custom function passed before sorting.
m2 = {"A":{"B":[3,5,2]}}
m2 = {"A":{"B":[3,5,2]}}
assert query(m2, ["A","B",H.ORDER]) == [2,3,5]
assert query(m2, ["A","B",(H.ORDER, str)]) == ["2","3","5"]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyspecter-0.1.1.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

pyspecter-0.1.1-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file pyspecter-0.1.1.tar.gz.

File metadata

  • Download URL: pyspecter-0.1.1.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.17

File hashes

Hashes for pyspecter-0.1.1.tar.gz
Algorithm Hash digest
SHA256 aeb2a4254f55c3863b5004cbd08f82f4b1eea1428d80f2a4553ab3db2dd01a55
MD5 777a515674ca18bb069a265a1ba13bac
BLAKE2b-256 693e9cf1083e08aada33115d2deb5215626a38c32325f76f1a26e29a005af047

See more details on using hashes here.

File details

Details for the file pyspecter-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pyspecter-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 6.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.17

File hashes

Hashes for pyspecter-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1101f053408fd7927eb7bf6cb89c6aeff3c0ba6de756195e773ada01f4a6ad43
MD5 c0ce680aeb69d0fdd4cd4fe69ea70b08
BLAKE2b-256 1d0fae4b663ae3324346bec9ff6a7a3b46583f4f94252b533fb4cc1f0af8167c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page