Welcome to parameter’s documentation!¶
Parameter is using to get and check HTTP parameters like use ORM.
Benefits¶
- Less code to check arguments.
- Pass http arguments to other function with a single object.
- IDE friendly, IDE can easily detect the complation.
- Easy to linter, the linter can easily detect attribute error.
Example with tornado¶
Normal pattern¶
from tornado import web
class DemoHandler(web.RequestHandler):
def get(self):
action = self.get_argument("action", None)
arg1 = self.get_argument("arg1", None)
arg2 = self.get_argument("arg2", None)
# ...
if action:
pass
if arg1:
pass
# ...
do(action, arg1, arg2, ...)
Parameter pattern¶
from tornado import web
from parameter import Model, Argument
from parameter import types
from parameter.adapter import TornadoAdapter
class DemoEntity(Model):
action = Argument("action", types.String, required=False,
miss_message="Please choose action",
invalid_message="Invalid action")
arg1 = Argument("arg1", types.Integer)
arg2 = Argument("arg2", types.Double)
# ...
class DemoHandler(web.RequestHandler):
def get(self):
demo = DemoEntity(TornadoAdapter(self))
do(demo)
Contents:
Guide¶
Define model¶
Inherit from Model
and use Argument
to define
a model.
from parameter import Model, Argument
from parameter import types
class Person(Model):
name = Argument(types.String)
age = Argument(types.Integer)
After model defined, you can use an adapter to create a instance.
from parameter.adapter import JSONAdapter
person = Person(JSONAdapter({"name": "Gray", "age": 18}))
print(person.name) # output: Gray
print(person.age) # output: 18
Alias¶
If a parameter’s name is not same with the attribute name, we can use alias
.
from parameter import Model, Argument
from parameter import types
class Person(Model):
children = Argument(types.String, alias="child", multiple=True)
The above code will map child
argument to the children
.
List¶
If a parameter have mulitple arguments, just set mulitple=True
in Argument
.
from parameter import Model, Argument
from parameter import types
class Person(Model):
name = Argument(types.String)
age = Argument(types.Integer)
children = Argument(types.String, alias="child", multiple=True)
# Assume the request is: /person?name=Gray&age=18&child=Tom&child=Jim
person = Person(DemoAdapter(request))
print(person.name) # output: Gray
print(person.age) # output: 18
print(person.children) # maybe output: ["Tom", "Jim"]
Nested¶
parameter
support nested by parameter.types.Nested
.
from parameter import Model, Argument
from parameter import types
from parameter.adapter import JSONAdapter
class Person(Model):
name = Argument(types.String)
age = Argument(types.Integer)
class Computer(Model):
arch = Argument(types.String)
belong = Argument(types.Nested(Person))
computer = Computer(JSONAdapter({"arch": "x86", "belong": {"name": "Gray", "age": 10}}))
assert computer.arch == "x86"
assert isinstance(computer.person, Person)
assert computer.person.name == "Gray"
assert computer.person.age == 18
List nested¶
parameter
nested also can be a list with mulitple
argument.
from parameter import Model, Argument
from parameter import types
from parameter.adapter import JSONAdapter
class Computer(Model):
arch = Argument(types.String)
class Person(Model):
name = Argument(types.String)
age = Argument(types.Integer)
computers = Argument(types.Nested(Computer), multiple=True)
person = Person(JSONAdapter({"name": "Gray", "age": 10, "computers": [
{"arch": "x86"},
{"arch": "x86_64"},
]}))
assert person.name == "Gray"
assert person.age == 18
assert isinstance(person.computers, list)
assert len(person.computers) == 2
assert isinstance(person.computers[0], Computer)
assert isinstance(person.computers[1], Computer)
assert person.computers[0].arch == "x86"
assert person.computers[1].arch == "x86_64"
Handling exception¶
While creating model, there two exceptions that user must to care:
parameter.exception.ArgumentMissError
: Raising when argument is missingparameter.exception.ArgumentInvalidError
: Raising when argument is invalid
Argument¶
-
class
parameter.model.
Argument
(type_, default=[], alias=None, multiple=False, miss_message=None, invalid_message=None)[source]¶ Represents a parameter in HTTP request.
-
__init__
(type_, default=[], alias=None, multiple=False, miss_message=None, invalid_message=None)[source]¶ Initialize
Parameters: - type (
parameter.types.BaseType
.) – The parameter’s type, indicated using an instance which subclassesparameter.types.BaseType
. - default – The default value.
- alias – The alias name of this argument as represented in the HTTP request.
- multiple – This argument have multiple values.
- miss_message – The message of
ArgumentMissError
- invalid_message – The message of
ArgumentInvalidError
- type (
-
convert
(value)[source]¶ Check and convert the value to the specified type.
Raises: ArgumentMissError
Raises: ArgumentInvalidError
-
Types¶
Add custom type¶
If you want add your own type, you need inherit from
BaseType
and override the abstract method
convert
. It used to convert an raw value from request to the current
type.
Here is an example:
from parameter.types import BaseType
class CVSList(BaseType):
def convert(self, val):
return val.split(",")
The above type receive a string value, and returns a list that split by comma.
Then you can use the type you have defined.
from parameter import Model, Argument
class DemoEntity(Model):
names = Argument("names", CVSList)
If you want some custom options, you can define the constructor method.
from parameter.types import BaseType
class CVSList(BaseType):
def __init__(self, separator=","):
self.separator = separator
def convert(self, val):
return val.split(self.separator)
The you can define a different separator.
from parameter import Model, Argument
class DemoEntity(Model):
names = Argument("names", CVSList(separator="|"))
-
class
parameter.types.
BaseType
[source]¶ Base class of the types.
-
convert
(val)[source]¶ Convert a value to this type.
Raises: parameter.exception.MismatchError
-
-
class
parameter.types.
Nested
(model_cls)[source]¶ -
convert
(adapter)[source]¶ Returns an instance which subclasses
Model
Parameters: adapter ( BaseAdapter
) – Adapter of the hosted model.
-
Adapters¶
Tornado adapter¶
-
class
parameter.adapter.
TornadoAdapter
(handler)[source]¶ Tornado adapter.
Usage:
from tornado import web from parameter import Model, Argument, types from parameter.adapter import TornadoAdapter class UserEntity(Model): username = Argument("username", types.String, max_len=100) password = Argument("password", types.String, max_len=64) name = Argument("name", types.Unicode, max_len=50) arg = Argument("age", types.Integer, default=18) class DemoHandler(web.RequestHandler): def get(self): entity = UserEntity(TornadoAdapter(self)) self.write({ "name": entity.name, "age": entity.age, })
JSON adapter¶
-
class
parameter.adapter.
JSONAdapter
(data)[source]¶ JSON adapter to get arguments from a JSON object.
Usage:
from parameter import Model, Argument, types from parameter.adapter import JSONAdapter data = {"a": 1, "b": 2} class DataEntity(Model): a = Argument("a", types.Integer) b = Argument("b", types.Integer) adapter = JSONAdapter(data) entity = DataEntity(adapter) print(entity.a) # 1 print(entity.b) # 2
Nested:
from parameter import Model, Argument, types from parameter.adapter import JSONAdapter data = {"a": 1, "b": 2, "person": {"age": 18, "name": "Gray"}} class PersonEntity(Model): are = Argument("age", types.Integer) name = Argument("name", types.Unicode) class DataEntity(Model): a = Argument("a", types.Integer) b = Argument("b", types.Integer) person = Argument("person", types.Nested(PersonEntity)) adapter = JSONAdapter(data) entity = DataEntity(adapter) print(entity.a) # 1 print(entity.b) # 2 print(entity.person.age) # 18 print(entity.person.name) # Gray
Add custom adapter¶
-
class
parameter.model.
BaseAdapter
[source]¶ To implement your own adapter, you need inherit from
BaseAdapter
.There two methods must be overwirtten:
get_argument
: Returns a single valueget_arguments
: Returns a sequence of values.
Example:
from parameter.model import BaseAdapter class DemoAdapter(BaseAdapter): "demo adapter" def __init__(self, arguments): self.arguments = arguments def get_argument(self, name, default): return self.arguments.get(name, default) def get_arguments(self, name): return self.arguments.getlist(name)
If you want your adapter to support nested, you need to override the
spawn
method, this method use the given value to return an new instance of the current adapter.from parameter.model import BaseAdapter class DemoAdapter(BaseAdapter): # see above def spawn(self, arguments): return DemoAdapter(arguments)
-
get_argument
(name, default, *args, **kwargs)[source]¶ Returns the argument’s value via
name
.Parameters: - name – The name of the argument.
- default – The default value.
Raises: Raises:
-
get_arguments
(name, *args, **kwargs)[source]¶ Returns the argument’s values via
name
.Parameters: name – The name of the argument. Raises: ArgumentMissError
Raises: ArgumentInvalidError
Exceptions¶
Exceptions of this package.