gstorm


Namegstorm JSON
Version 0.12.4 PyPI version JSON
download
home_pagehttps://github.com/valiot/python-gstorm
SummaryGraphQL ORM for python (based on pygqlc)
upload_time2023-05-24 14:49:33
maintainer
docs_urlNone
authorValiot
requires_python
license
keywords gstorm orm graphql gql
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ### never forget:
`python setup.py sdist bdist_wheel && python -m twine upload dist/* --skip-existing # UPLOAD TO PYPI`

# python-gstorm
Graphql Simple Tiny Object Relational Mapping - Graphql ORM for python

# Current features:

## QUERY
### Aliases
There are several aliases for most Query-building functions, which make queries more concise:
- query
  - q = query, example: `Type.q() # vs Type.query()`
  - qm = query, example: `Type.qm() # vs Type.query()`
- query_one
  - q1 = query_one, example: `Type.q1() # vs Type.query_one()`
  - qs = query_one, example: `Type.qs() # vs Type.query_one()`
- filter
  - fil = filter, example: `Type.q().fil(...) # vs Type.query().filter(...)`
  - after
    - long: `Type.query().filter(after={'attribute': x, 'date': y})`
    - short: `Type.q().after(attr=x, date=y)`
  - before
    - long: `Type.query().filter(before={'attribute': x, 'date': y})`
    - short: `Type.q().before(attr=x, date=y)`
  - isNull
    - long: `Type.query().filter(nullAttribute={'attribute': x, 'isNull': y})`
    - short: `Type.q().isNull(attr=x, value=True)`
    - shorter: `Type.q().isNull(attr=x)` (Defaults to True)
- findBy
  - fb = findBy, example: `Type.q(). # vs Type.query().`
  - find = findBy, example: `Type.q(). # vs Type.query().`
- orderBy
  - ob = orderBy, example: `Type.q(). # vs Type.query().`
  - order = orderBy, example: `Type.q(). # vs Type.query().`
- limit
  - lim = limit, example: `Type.q(). # vs Type.query().`
- offset
  - off = offset, example: `Type.q(). # vs Type.query().`
- children
  - child = children, example: `Type.q(). # vs Type.query().`
  - ch = children, example: `Type.q(). # vs Type.query().`
- get
  - run = get
### Query all
```python
from tests.models import Tank
all_tanks = Tank.query().get() # returns -> List[Tank]
print(all_tanks) # [Tank(id=1,capacity=10),Tank(id=2,capacity=20),...]
```
### Query some
You can concatenate storm methods to manipulate the data and how you want to receive it,
this methods may receive parameters in several ways:
- filter(kwargs):
  - `.filter(name='L1')`
  - `.filter({'name': 'L1'})`
  - `.filter(name='L1').filter(capacity=1250)`
  - `.filter(name='L1', capacity=1250)`
  - `.filter({'name': 'L1', 'capacity': 1250})`
- orderBy(kwarg):
  - Accepted keys = [asc, desc]
  - Accepted values = GraphQLType ModelAttr enums. 
  - `.orderBy(asc=TypeAttrs.ID)`
  - `.orderBy(desc=TypeAttrs.INSERTED_AT)`
- limit(count)
  - `.limit(1)`
```python
from tests.models import Tank
all_tanks = (
  Tank.query()
  .filter(capacity=1250)
).get() # returns -> List[Tank]
print(all_tanks) # [Tank(id=1,capacity=10),Tank(id=3,capacity=10),...]
```
### Query one
```python
from tests.models import Tank
my_tank = Tank.query_one().findBy(id=3).get() # returns -> Tank
print(my_tank) # Tank(id='3', name='R342', type='Reposo', capacity=0, room=None, inventories=[])
```
### Filters
#### per field value (exact match, regex accepted)
```python
from tests.models import Tank
gov_tanks = Tank.query().filter(type='^Gob').get()
rest_tanks = Tank.query().filter(type='^Rep').get()
print(len(gov_tanks))
print(len(rest_tanks))
```
#### Null attribute
```python
from tests.models import Tank
ok_tanks = (
  Tank.query().filter(nullAttribute= { 'attribute': 'CAPACITY', 'isNull': False })
).get()
print(ok_tanks)

# short-hand version
from tests.models import Tank
ok_tanks = Tank.q().isNull(attr='CAPACITY', value=False).get()
print(ok_tanks)

# using null default value:
from tests.models import Tank
bad_tanks = Tank.q().isNull(attr='CAPACITY').get() # value param defaults to True
print(bad_tanks)
```

#### Comparison dates (after, before)
```python
from tests.models import BbtInventory
from datetime import datetime as dt, timedelta as td
from gstorm.helpers.date_helpers import get_iso8601_str
today = get_iso8601_str(dt.now() - td(days=1))
yesterday = get_iso8601_str(dt.now() - td(days=2))
today_inventories = (
  BbtInventory.query()
    .filter(after={
      'attribute': 'INSERTED_AT',
      'date': "2020-02-27T23:01:44Z" # or: 'date': dt.now() - td(days=1)
    })
).get()
print(today_inventories)

# Short-hand version
today_inventories = (
  BbtInventory.query()
    .after(attr='INSERTED_AT', date="2020-02-27T23:01:44Z") # or: 'date': dt.now() - td(days=1)
).get()
print(today_inventories)

# Short-hand version
yesterday_inventories = (
  BbtInventory.query()
    .after(attr='INSERTED_AT', date=yesterday)
    .before(attr='INSERTED_AT', date=today)
).get()
print(yesterday_inventories)
```
### Ordering
#### Asc, Desc, per field
```python
from tests.models import BbtInventory
latest_inventories = BbtInventory.query().orderBy(desc=BbtInventoryAttrs.ID).limit(5).get()
print(latest_inventories)
smallest_inventories = BbtInventory.query().orderBy(asc=BbtInventoryAttrs.VOLUME).limit(5).get()
print(smallest_inventories)
```
### Limit
```python
from tests.models import BottlingLine
first_10_lines = BottlingLine.query().limit(10).get()
print(first_10_lines)
```
### Nested Queries
```python
from tests.models import BottlingOrder
# We want to include the sub-attributes:
guid = 'abc123'
orders = BottlingOrder.query()._with({
  'line': Line.query(),
  'plans': BottlingPlan.query().orderBy(asc=BottlingPlanAttrs.ID),
  'brightBeer': BrightBeer.query().filter(groupGuid=guid))
}).
print(orders[0])
# >> BottlingOrder(id=1, name='123', line=Line(name='LINEA001'), ...)
```
### Pagination (API NOT FINAL)
#### iterable
```python
from tests.models import Datum
order = {'desc': 'ID'}
for datum_page in Datum.limit(100).offset(0).orderBy(asc=DatumAttrs.ORDER).paginate():
  for datum in datum_page:
    print(datum) # type: Datum(id=x,value=y)
```
#### Comparison numerical (>, >=, <, <=...)
NOT WORKING IN VALIOT-APP

# MUTATION
## Create
```python
from tests.models import Tank
tank = Tank.load(csv='tanks.csv').limit(1).get() # load from any source
response = storm.create(tank) # GraphqlType object
```
## Update
```python
from tests.models import Tank
[gov_tank] = Tank.query().filter(name='L').limit(1).get()
# process data...
# ...
response = storm.update(gov_tank).apply() # GraphqlType object
```
## Upsert
```python
from tests.models import Tank
[gov_tank] = Tank.load(csv='tanks.csv').limit(1).get() # load from any source
response = storm.upsert(gov_tank).apply() # GraphqlType object
if not response.successful:
  print(response.messages)
# everything ok, do other stuff...
print(gov_tank) # has updated data (New ID, etc)
```
## Single mutation
**See above examples**
## Multiple mutation
### Sequential
```python
from tests.models import Tank
gov_tanks = Tank.load(csv='tanks.csv').get() # load from any source
# ! OPTION 1: one by one
for tank in gov_tanks:
  response = storm.upsert(tank).apply() # GraphqlType object
  print(tank) # has updated data (New ID, etc)
# ! OPTION 2: All handled by storm:
response = storm.upsert(gov_tanks).apply()
# response type -> List[GraphqlMutationResponse]
```
### Batch (Multiple mutations in single Mutation tag)
```python
from tests.models import Tank
from storm import UploadMode as mode
gov_tanks = Tank.load(csv='tanks.csv') # load from any source
response = storm.upsert(gov_tanks).mode(mode.BATCH).apply()
# default:
# response = storm.upsert(gov_tanks, mode=mode.SEQUENTIAL)
```
### Nested mutation
**API WIP**:
```python
from tests.models import BbtProgram, BbtPlan
from storm import UploadMode as mode
# algorithm runs...
program = BbtProgram() # New with defaults
for plan in algorithm_plans:
  program.plans.append(BbtPlan(**plan))
# OPTION 1:
response = storm.create(program)
  .nested({
    'plans': Plan.create()
  }).apply()
# OPTION 2:
attrs = ['plans']
response = storm.create(program, nested=attrs)
```

### Parallel/Batch (Multiple mutations multi-threaded, each mutation may be batched)
NOT PRIORITY
# SUBSCRIPTION
NOT PRIORITY

## COMPARISON
```
# # ! old way [No additional libraries]:
# import requests
# import json
# @dataclass
# class Line():
#   id: str
#   name: str
#   speed: float

# LINE = '''
#   query getLine($name: String!){
#     line(findBy:{ name: $name }){
#       id
#       name
#       speed
#     }
#   }
# '''
# url = 'https://test.valiot.app/'
# content = {
#   'query': LINE,
#   'variables': {'name': 'LINEA001'}
# }
# response = requests.post(url, json=content)
# line_data = json.loads(str(response.content))
# line = Line(**line_data)
# line.name # * >> LINEA001
# # ! current way [pygqlc]:
# gql = GraphQLClient()
# @dataclass
# class Line():
#   id: str
#   name: str
#   speed: float

# LINE = '''
#   query getLine($name: String!){
#     line(findBy:{ name: $name }){
#       id
#       name
#       speed
#     }
#   }
# '''
# line_data, _ = gql.query_one(LINE, {'name': 'LINEA001'})
# line = Line(**line_data)
# line.name # * >> LINEA001

# # * New way (TBD):
# gql = GraphQLClient()
# orm = GStorm(client=gql, schema=SCHEMA_PATH)
# Line = orm.getType('Line')
# line = Line.find_one({'name': 'LINEA001'})
# line.name # * >> LINEA001
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/valiot/python-gstorm",
    "name": "gstorm",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "gstorm,orm,graphql,gql",
    "author": "Valiot",
    "author_email": "hiring@valiot.io",
    "download_url": "https://files.pythonhosted.org/packages/89/c0/1792c7ff4eed9990dac39449a4f123b4546485c1d394bc95a17eb5130a06/gstorm-0.12.4.tar.gz",
    "platform": null,
    "description": "### never forget:\n`python setup.py sdist bdist_wheel && python -m twine upload dist/* --skip-existing # UPLOAD TO PYPI`\n\n# python-gstorm\nGraphql Simple Tiny Object Relational Mapping - Graphql ORM for python\n\n# Current features:\n\n## QUERY\n### Aliases\nThere are several aliases for most Query-building functions, which make queries more concise:\n- query\n  - q = query, example: `Type.q() # vs Type.query()`\n  - qm = query, example: `Type.qm() # vs Type.query()`\n- query_one\n  - q1 = query_one, example: `Type.q1() # vs Type.query_one()`\n  - qs = query_one, example: `Type.qs() # vs Type.query_one()`\n- filter\n  - fil = filter, example: `Type.q().fil(...) # vs Type.query().filter(...)`\n  - after\n    - long: `Type.query().filter(after={'attribute': x, 'date': y})`\n    - short: `Type.q().after(attr=x, date=y)`\n  - before\n    - long: `Type.query().filter(before={'attribute': x, 'date': y})`\n    - short: `Type.q().before(attr=x, date=y)`\n  - isNull\n    - long: `Type.query().filter(nullAttribute={'attribute': x, 'isNull': y})`\n    - short: `Type.q().isNull(attr=x, value=True)`\n    - shorter: `Type.q().isNull(attr=x)` (Defaults to True)\n- findBy\n  - fb = findBy, example: `Type.q(). # vs Type.query().`\n  - find = findBy, example: `Type.q(). # vs Type.query().`\n- orderBy\n  - ob = orderBy, example: `Type.q(). # vs Type.query().`\n  - order = orderBy, example: `Type.q(). # vs Type.query().`\n- limit\n  - lim = limit, example: `Type.q(). # vs Type.query().`\n- offset\n  - off = offset, example: `Type.q(). # vs Type.query().`\n- children\n  - child = children, example: `Type.q(). # vs Type.query().`\n  - ch = children, example: `Type.q(). # vs Type.query().`\n- get\n  - run = get\n### Query all\n```python\nfrom tests.models import Tank\nall_tanks = Tank.query().get() # returns -> List[Tank]\nprint(all_tanks) # [Tank(id=1,capacity=10),Tank(id=2,capacity=20),...]\n```\n### Query some\nYou can concatenate storm methods to manipulate the data and how you want to receive it,\nthis methods may receive parameters in several ways:\n- filter(kwargs):\n  - `.filter(name='L1')`\n  - `.filter({'name': 'L1'})`\n  - `.filter(name='L1').filter(capacity=1250)`\n  - `.filter(name='L1', capacity=1250)`\n  - `.filter({'name': 'L1', 'capacity': 1250})`\n- orderBy(kwarg):\n  - Accepted keys = [asc, desc]\n  - Accepted values = GraphQLType ModelAttr enums. \n  - `.orderBy(asc=TypeAttrs.ID)`\n  - `.orderBy(desc=TypeAttrs.INSERTED_AT)`\n- limit(count)\n  - `.limit(1)`\n```python\nfrom tests.models import Tank\nall_tanks = (\n  Tank.query()\n  .filter(capacity=1250)\n).get() # returns -> List[Tank]\nprint(all_tanks) # [Tank(id=1,capacity=10),Tank(id=3,capacity=10),...]\n```\n### Query one\n```python\nfrom tests.models import Tank\nmy_tank = Tank.query_one().findBy(id=3).get() # returns -> Tank\nprint(my_tank) # Tank(id='3', name='R342', type='Reposo', capacity=0, room=None, inventories=[])\n```\n### Filters\n#### per field value (exact match, regex accepted)\n```python\nfrom tests.models import Tank\ngov_tanks = Tank.query().filter(type='^Gob').get()\nrest_tanks = Tank.query().filter(type='^Rep').get()\nprint(len(gov_tanks))\nprint(len(rest_tanks))\n```\n#### Null attribute\n```python\nfrom tests.models import Tank\nok_tanks = (\n  Tank.query().filter(nullAttribute= { 'attribute': 'CAPACITY', 'isNull': False })\n).get()\nprint(ok_tanks)\n\n# short-hand version\nfrom tests.models import Tank\nok_tanks = Tank.q().isNull(attr='CAPACITY', value=False).get()\nprint(ok_tanks)\n\n# using null default value:\nfrom tests.models import Tank\nbad_tanks = Tank.q().isNull(attr='CAPACITY').get() # value param defaults to True\nprint(bad_tanks)\n```\n\n#### Comparison dates (after, before)\n```python\nfrom tests.models import BbtInventory\nfrom datetime import datetime as dt, timedelta as td\nfrom gstorm.helpers.date_helpers import get_iso8601_str\ntoday = get_iso8601_str(dt.now() - td(days=1))\nyesterday = get_iso8601_str(dt.now() - td(days=2))\ntoday_inventories = (\n  BbtInventory.query()\n    .filter(after={\n      'attribute': 'INSERTED_AT',\n      'date': \"2020-02-27T23:01:44Z\" # or: 'date': dt.now() - td(days=1)\n    })\n).get()\nprint(today_inventories)\n\n# Short-hand version\ntoday_inventories = (\n  BbtInventory.query()\n    .after(attr='INSERTED_AT', date=\"2020-02-27T23:01:44Z\") # or: 'date': dt.now() - td(days=1)\n).get()\nprint(today_inventories)\n\n# Short-hand version\nyesterday_inventories = (\n  BbtInventory.query()\n    .after(attr='INSERTED_AT', date=yesterday)\n    .before(attr='INSERTED_AT', date=today)\n).get()\nprint(yesterday_inventories)\n```\n### Ordering\n#### Asc, Desc, per field\n```python\nfrom tests.models import BbtInventory\nlatest_inventories = BbtInventory.query().orderBy(desc=BbtInventoryAttrs.ID).limit(5).get()\nprint(latest_inventories)\nsmallest_inventories = BbtInventory.query().orderBy(asc=BbtInventoryAttrs.VOLUME).limit(5).get()\nprint(smallest_inventories)\n```\n### Limit\n```python\nfrom tests.models import BottlingLine\nfirst_10_lines = BottlingLine.query().limit(10).get()\nprint(first_10_lines)\n```\n### Nested Queries\n```python\nfrom tests.models import BottlingOrder\n# We want to include the sub-attributes:\nguid = 'abc123'\norders = BottlingOrder.query()._with({\n  'line': Line.query(),\n  'plans': BottlingPlan.query().orderBy(asc=BottlingPlanAttrs.ID),\n  'brightBeer': BrightBeer.query().filter(groupGuid=guid))\n}).\nprint(orders[0])\n# >> BottlingOrder(id=1, name='123', line=Line(name='LINEA001'), ...)\n```\n### Pagination (API NOT FINAL)\n#### iterable\n```python\nfrom tests.models import Datum\norder = {'desc': 'ID'}\nfor datum_page in Datum.limit(100).offset(0).orderBy(asc=DatumAttrs.ORDER).paginate():\n  for datum in datum_page:\n    print(datum) # type: Datum(id=x,value=y)\n```\n#### Comparison numerical (>, >=, <, <=...)\nNOT WORKING IN VALIOT-APP\n\n# MUTATION\n## Create\n```python\nfrom tests.models import Tank\ntank = Tank.load(csv='tanks.csv').limit(1).get() # load from any source\nresponse = storm.create(tank) # GraphqlType object\n```\n## Update\n```python\nfrom tests.models import Tank\n[gov_tank] = Tank.query().filter(name='L').limit(1).get()\n# process data...\n# ...\nresponse = storm.update(gov_tank).apply() # GraphqlType object\n```\n## Upsert\n```python\nfrom tests.models import Tank\n[gov_tank] = Tank.load(csv='tanks.csv').limit(1).get() # load from any source\nresponse = storm.upsert(gov_tank).apply() # GraphqlType object\nif not response.successful:\n  print(response.messages)\n# everything ok, do other stuff...\nprint(gov_tank) # has updated data (New ID, etc)\n```\n## Single mutation\n**See above examples**\n## Multiple mutation\n### Sequential\n```python\nfrom tests.models import Tank\ngov_tanks = Tank.load(csv='tanks.csv').get() # load from any source\n# ! OPTION 1: one by one\nfor tank in gov_tanks:\n  response = storm.upsert(tank).apply() # GraphqlType object\n  print(tank) # has updated data (New ID, etc)\n# ! OPTION 2: All handled by storm:\nresponse = storm.upsert(gov_tanks).apply()\n# response type -> List[GraphqlMutationResponse]\n```\n### Batch (Multiple mutations in single Mutation tag)\n```python\nfrom tests.models import Tank\nfrom storm import UploadMode as mode\ngov_tanks = Tank.load(csv='tanks.csv') # load from any source\nresponse = storm.upsert(gov_tanks).mode(mode.BATCH).apply()\n# default:\n# response = storm.upsert(gov_tanks, mode=mode.SEQUENTIAL)\n```\n### Nested mutation\n**API WIP**:\n```python\nfrom tests.models import BbtProgram, BbtPlan\nfrom storm import UploadMode as mode\n# algorithm runs...\nprogram = BbtProgram() # New with defaults\nfor plan in algorithm_plans:\n  program.plans.append(BbtPlan(**plan))\n# OPTION 1:\nresponse = storm.create(program)\n  .nested({\n    'plans': Plan.create()\n  }).apply()\n# OPTION 2:\nattrs = ['plans']\nresponse = storm.create(program, nested=attrs)\n```\n\n### Parallel/Batch (Multiple mutations multi-threaded, each mutation may be batched)\nNOT PRIORITY\n# SUBSCRIPTION\nNOT PRIORITY\n\n## COMPARISON\n```\n# # ! old way [No additional libraries]:\n# import requests\n# import json\n# @dataclass\n# class Line():\n#   id: str\n#   name: str\n#   speed: float\n\n# LINE = '''\n#   query getLine($name: String!){\n#     line(findBy:{ name: $name }){\n#       id\n#       name\n#       speed\n#     }\n#   }\n# '''\n# url = 'https://test.valiot.app/'\n# content = {\n#   'query': LINE,\n#   'variables': {'name': 'LINEA001'}\n# }\n# response = requests.post(url, json=content)\n# line_data = json.loads(str(response.content))\n# line = Line(**line_data)\n# line.name # * >> LINEA001\n# # ! current way [pygqlc]:\n# gql = GraphQLClient()\n# @dataclass\n# class Line():\n#   id: str\n#   name: str\n#   speed: float\n\n# LINE = '''\n#   query getLine($name: String!){\n#     line(findBy:{ name: $name }){\n#       id\n#       name\n#       speed\n#     }\n#   }\n# '''\n# line_data, _ = gql.query_one(LINE, {'name': 'LINEA001'})\n# line = Line(**line_data)\n# line.name # * >> LINEA001\n\n# # * New way (TBD):\n# gql = GraphQLClient()\n# orm = GStorm(client=gql, schema=SCHEMA_PATH)\n# Line = orm.getType('Line')\n# line = Line.find_one({'name': 'LINEA001'})\n# line.name # * >> LINEA001\n```\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "GraphQL ORM for python (based on pygqlc)",
    "version": "0.12.4",
    "project_urls": {
        "Homepage": "https://github.com/valiot/python-gstorm"
    },
    "split_keywords": [
        "gstorm",
        "orm",
        "graphql",
        "gql"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d5af2e952c1e761dee7b1bca6584f98bcd0f04b8c8a5cb6c06ef7839fd35a69c",
                "md5": "18bcd7fcdf706d5aee36b5323ac3cd4e",
                "sha256": "f83c59c8660e1e32d3982f2393cd5eee51f854f9a31234af38680c8d5dc1e166"
            },
            "downloads": -1,
            "filename": "gstorm-0.12.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "18bcd7fcdf706d5aee36b5323ac3cd4e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 36244,
            "upload_time": "2023-05-24T14:49:31",
            "upload_time_iso_8601": "2023-05-24T14:49:31.058039Z",
            "url": "https://files.pythonhosted.org/packages/d5/af/2e952c1e761dee7b1bca6584f98bcd0f04b8c8a5cb6c06ef7839fd35a69c/gstorm-0.12.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "89c01792c7ff4eed9990dac39449a4f123b4546485c1d394bc95a17eb5130a06",
                "md5": "d3bfa006e1f487bc33f8bb5618f19e12",
                "sha256": "4c5541ded405706363a6717f1187b0af5061997de525d1d955700eeea100ce41"
            },
            "downloads": -1,
            "filename": "gstorm-0.12.4.tar.gz",
            "has_sig": false,
            "md5_digest": "d3bfa006e1f487bc33f8bb5618f19e12",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 33134,
            "upload_time": "2023-05-24T14:49:33",
            "upload_time_iso_8601": "2023-05-24T14:49:33.760688Z",
            "url": "https://files.pythonhosted.org/packages/89/c0/1792c7ff4eed9990dac39449a4f123b4546485c1d394bc95a17eb5130a06/gstorm-0.12.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-24 14:49:33",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "valiot",
    "github_project": "python-gstorm",
    "github_not_found": true,
    "lcname": "gstorm"
}
        
Elapsed time: 0.06163s