Skip to main content

algen

Project description

# Algen

Algen generates opionated ORM classes for sqlalchemy given a simple schema
either as a commandline string or as a yaml file.
It is designed to have minimal dependencies and is trivially extensible.
A command line tool is bundled along to help generate the models.
For DB specific types, only postgres is currently supported.
The tool currently assumes that sqlalchemy's declarative base object
is to be imported like ```from .alchemy_base import Base```


### CLI
```bash
$ algen --help
Usage: algen [OPTIONS]

Options:
-n, --name TEXT Name of model
-c, --columns TEXT Column definition. e.g. col_name:col_type Can be
used multiple times hence named columns. e.g. -c
foo:Int -c bar:Unicode(20)
-d, --destination PATH Destination directory. Default will assume 'Models'
directory inside the current working directory
-y, --yaml PATH Yaml file describing the Model. This supersedes the
column definition provided through --columns option.
--help Show this message and exit.
```

Given a file as follows:
```yaml
Person:
columns:
- name: id
type: BigInteger
primary_key: True
auto_increment: True
- name: name
type: Unicode(255)
- name: is_vip
type: Boolean
- name: created_at
type: DateTime(timezone=True)

Address:
columns:
- name: id
type: BigInteger
primary_key: True
auto_increment: True
- name: line1
type: Unicode()
- name: line2
type: Unicode()
- name: line3
type: Unicode()
- name: postcode
type: Unicode(10)
index: True
```

The cli tool will create two the following two files ```Person.py``` and ```Address.py```.

```python
from __future__ import unicode_literals, absolute_import, print_function

from collections import namedtuple

from sqlalchemy import Column, DateTime, Boolean, Unicode, BigInteger


from .alchemy_base import Base

__author__ = 'danishabdullah'


class Person(Base):
__tablename__ = 'persons'

id = Column(BigInteger, primary_key=True, auto_increment=True)
name = Column(Unicode(255), )
is_vip = Column(Boolean, )
created_at = Column(DateTime(timezone=True), )


def __init__(self, id=None, name=None, is_vip=None, created_at=None):
self.id = id
self.name = name
self.is_vip = is_vip
self.created_at = created_at

def add(self, session):
session.add(self)

def update(self, name=None, is_vip=None, created_at=None):
# This function only updates a value if it is not None.
# Falsy values go through in the normal way.
# To set things to None use the usual syntax:
# Person.column_name = None

if name is not None:
self.name = name

if is_vip is not None:
self.is_vip = is_vip

if created_at is not None:
self.created_at = created_at

def delete(self, session):
session.delete(self)

def to_dict(self):
return {x: y for x, y in self.__dict__.items() if not x.startswith("_sa")}

def get_proxy_cls(self):
# PersonProxy is useful when you want to persist data
# independent of the sqlalchemy session. It's just a namedtuple
# that has very low memory/cpu footprint compared the regular
# orm class instances.
keys = self.to_dict().keys()
name = "PersonProxy"
return namedtuple(name, keys)

def to_proxy(self):
# Proxy-ing is useful when you want to persist data
# independent of the sqlalchemy session. It's just a namedtuple
# that has very low memory/cpu footprint compared the regular
# orm class instances.
cls = self._get_proxy_cls()
return cls(**self.to_dict())

@classmethod
def from_proxy(cls, proxy):
return cls(**proxy._asdict())

def __hash__(self):
return hash(str(self.id))

def __eq__(self, other):
return (self.id == other.id)

def __neq__(self, other):
return not (self.id == other.id)

def __str__(self):
return "<Person: {id}>".format(id=self.id)

def __unicode__(self):
return "<Person: {id}>".format(id=self.id)

def __repr__(self):
return "<Person: {id}>".format(id=self.id)
```

```python
from __future__ import unicode_literals, absolute_import, print_function

from collections import namedtuple

from sqlalchemy import Column, Unicode, BigInteger


from .alchemy_base import Base

__author__ = 'danishabdullah'


class Address(Base):
__tablename__ = 'addresses'

id = Column(BigInteger, primary_key=True, auto_increment=True)
line1 = Column(Unicode(), )
line2 = Column(Unicode(), )
line3 = Column(Unicode(), )
postcode = Column(Unicode(10), index=True)


def __init__(self, id=None, line1=None, line2=None, line3=None, postcode=None):
self.id = id
self.line1 = line1
self.line2 = line2
self.line3 = line3
self.postcode = postcode

def add(self, session):
session.add(self)

def update(self, line1=None, line2=None, line3=None, postcode=None):
# This function only updates a value if it is not None.
# Falsy values go through in the normal way.
# To set things to None use the usual syntax:
# Address.column_name = None

if line1 is not None:
self.line1 = line1

if line2 is not None:
self.line2 = line2

if line3 is not None:
self.line3 = line3

if postcode is not None:
self.postcode = postcode

def delete(self, session):
session.delete(self)

def to_dict(self):
return {x: y for x, y in self.__dict__.items() if not x.startswith("_sa")}

def get_proxy_cls(self):
# AddressProxy is useful when you want to persist data
# independent of the sqlalchemy session. It's just a namedtuple
# that has very low memory/cpu footprint compared the regular
# orm class instances.
keys = self.to_dict().keys()
name = "AddressProxy"
return namedtuple(name, keys)

def to_proxy(self):
# Proxy-ing is useful when you want to persist data
# independent of the sqlalchemy session. It's just a namedtuple
# that has very low memory/cpu footprint compared the regular
# orm class instances.
cls = self._get_proxy_cls()
return cls(**self.to_dict())

@classmethod
def from_proxy(cls, proxy):
return cls(**proxy._asdict())

def __hash__(self):
return hash(str(self.id))

def __eq__(self, other):
return (self.id == other.id)

def __neq__(self, other):
return not (self.id == other.id)

def __str__(self):
return "<Address: {id}>".format(id=self.id)

def __unicode__(self):
return "<Address: {id}>".format(id=self.id)

def __repr__(self):
return "<Address: {id}>".format(id=self.id)

```

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

algen-0.9.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

algen-0.9.macosx-10.5-x86_64.tar.gz (17.3 kB view details)

Uploaded Source

File details

Details for the file algen-0.9.tar.gz.

File metadata

  • Download URL: algen-0.9.tar.gz
  • Upload date:
  • Size: 8.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for algen-0.9.tar.gz
Algorithm Hash digest
SHA256 39c693ced7064be557cf4b49334ab8e58de3ddf882d8d3b5b97d6c50e54e1a90
MD5 3073a40715371658018097e203aee53b
BLAKE2b-256 af541e880464ceb6fef076ab74d0d6e8d3a8e41cc222d37f38f35aa1c8df8713

See more details on using hashes here.

File details

Details for the file algen-0.9.macosx-10.5-x86_64.tar.gz.

File metadata

File hashes

Hashes for algen-0.9.macosx-10.5-x86_64.tar.gz
Algorithm Hash digest
SHA256 09b714a21306735bbc8a08685e60d793da1b15b5830b8187178b6a3a67d3e4ed
MD5 7a5ab3748c8ef420c87df955ef8d5ae1
BLAKE2b-256 06d8b89d06a99d847602fa295fb10458e9a4aec0c90b101d7e5658ff5cbabc84

See more details on using hashes here.

Supported by

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