Skip to main content

MetaClass supporting fine grained control of object creationand initialization

Project description

metaparams
==========

.. image:: https://img.shields.io/pypi/v/metaparams.svg
:alt: PyPi Version
:scale: 100%
:target: https://pypi.python.org/pypi/metaparams/

.. image:: https://img.shields.io/pypi/dm/metaparams.svg
:alt: PyPi Monthly Donwloads
:scale: 100%
:target: https://pypi.python.org/pypi/metaparams/

.. image:: https://img.shields.io/pypi/l/metaparams.svg
:alt: License
:scale: 100%
:target: https://github.com/mementum/metaparams/blob/master/LICENSE

.. image:: https://travis-ci.org/mementum/metaparams.png?branch=master
:alt: Travis-ci Build Status
:scale: 100%
:target: https://travis-ci.org/mementum/metaparams

.. image:: https://readthedocs.org/projects/metaparams/badge/?version=latest
:alt: Documentation Status
:scale: 100%
:target: https://readthedocs.org/projects/metaparams/

.. image:: https://img.shields.io/pypi/pyversions/metaparams.svg
:alt: Pytghon versions
:scale: 100%
:target: https://pypi.python.org/pypi/metaparams/

``metaparams`` is a MetaClass/Class/Decorator infrastructure to define params
without invoking objects and have them automatically parse/remove the ``kwargs``
passed to the class in which they are intalled

Documentation
=============

Read the full documentation at readthedocs.org:

- `metaparams documentation <http://metaparams.readthedocs.org/en/latest/introduction.html>`_

Python 2/3 Support
==================

- Python 2.7
- Python 3.2/3.3/3.4/3.5

- It also works with pypy and pypy3

Installation
============

From pypi::

pip install metaparams

From source:

- Place the *metaparams* directory found in the sources inside your project

Features:
=========

- ``metaparams`` decorator to params-enable any class

- ``ParamsBase`` a class from which to subclass to also be params-enabled

- ``MetaParams`` a MetaClass for more complex usage pattern


Quick Usage
===========

The example below is available in the source as a single file test. It's broken
down into parts to ease up reading::

from __future__ import (absolute_import, division, print_function,
unicode_literals)


from metaparams import metaparams, MetaParams, ParamsBase

print('=' * 50)
print('Creating A with params with DECORATOR')


@metaparams()
class A(object):

params = (
('p1', True, 'doc'),
('p2', 99),
)

def __init__(self):
pass

print('-- Instantiating A with no kwargs')
a = A()

# Defined params are reachable below the attribute params
print('a.params.p1:', a.params.p1)
print('a.params.p2:', a.params.p2)

# Modification of default values can be checked
print('Checking if p1 has default value:', a.params._isdefault('p1'))

print('=' * 50)
print('Creating B as subclass from A, changing p1, adding p3')

This first part produces the following output::

==================================================
Creating A with params with DECORATOR
-- Instantiating A with no kwargs
a.params.p1: True
a.params.p2: 99
Checking if p1 has default value: True

The 2nd part::

# Inheriting with modification an extension
class B(A):

params = (
('p1', False,), # changed default value of p1
('p3', None), # new parameter
)

def __init__(self):
pass

print('-- Instantiating B with no kwargs')
b = B()

# Defined params are reachable below the attribute params
print('b.param.p1 (default changed):', b.params.p1)
print('b.params.p2 (same default):', b.params.p2)
print('b.params.p3 (new param):', b.params.p3)

# Modification of default values can be checked
print('Checking if p1 has default value:', b.params._isdefault('p1'))

# Over the class we can also check defaults
# B has different default value for p1 than A
print('Checking default in B for p1 is not the same as default in A:',
b.params.p1 != A.params._default('p1'))

Output::

==================================================
Creating B as subclass from A, changing p1, adding p3
-- Instantiating B with no kwargs
b.param.p1 (default changed): False
b.params.p2 (same default): 99
b.params.p3 (new param): None
Checking if p1 has default value: True
Checking default in B for p1 is not the same as default in A: True


3rd part::

print('=' * 50)
print('Recreating A with Decorator - name is "kargs" and short alias')


# The name of the attribute 'params' can be changed
# and a shorter alias (PEP-8 ...) added
@metaparams(_pname='kargs', _pshort=True)
class A(object):

kargs = (
('p1', True, 'doc'),
('p2', 99),
)

def __init__(self):
pass

print('-- Instantiating A with no kwargs')
a = A()

# Defined params are reachable below the attribute params
print('Checking if a params are reachable over "kargs"')
print('a.kargs.p1:', a.kargs.p1)
print('a.kargs.p2:', a.kargs.p2)

print('Checking if a params are reachable over shorter alias "k"')
print(a.k.p1)
print(a.k.p2)

# Modification of default values can be checked
print('Checking if p1 has default value:', a.kargs._isdefault('p1'))

Output::

==================================================
Recreating A with Decorator - name is "kargs" and short alias
-- Instantiating A with no kwargs
Checking if a params are reachable over "kargs"
a.kargs.p1: True
a.kargs.p2: 99
Checking if a params are reachable over shorter alias "k"
True
99
Checking if p1 has default value: True


4th part::

print('=' * 50)
print('Recreating A with new attr for params - "kargs" and short alias')
print('USING THE METACLASS')


# The metaclass works also so ... but it's a metaclass
class A(MetaParams.as_metaclass(_pname='kargs', _pshort=True)):

kargs = (
('p1', True, 'doc'),
('p2', 99),
)

def __init__(self):
pass

a = A()

# Defined params are reachable below the attribute params
print('Checking if a params are reachable over "kargs"')
print('a.kargs.p1:', a.kargs.p1)
print('a.kargs.p2:', a.kargs.p2)

print('Checking if a params are reachable over shorter alias "k"')
print(a.k.p1)
print(a.k.p2)

# Modification of default values can be checked
print('Checking if p1 has default value:', a.kargs._isdefault('p1'))

Output::

==================================================
Recreating A with new attr for params - "kargs" and short alias
USING THE METACLASS
Checking if a params are reachable over "kargs"
a.kargs.p1: True
a.kargs.p2: 99
Checking if a params are reachable over shorter alias "k"
True
99
Checking if p1 has default value: True


Final part::

print('=' * 50)
print('Recreating A with ParamsBase ... nothing can be changed')

# And finally an already cooked base class with no customization
class A(ParamsBase):

params = (
('p1', True, 'doc'),
('p2', 99),
)

def __init__(self):
pass

a = A()

# Defined params are reachable below the attribute params
print('a.params.p1:', a.params.p1)
print('a.params.p2:', a.params.p2)

# Modification of default values can be checked
print('Checking if p1 has default value:', a.params._isdefault('p1'))

Output::

==================================================
Recreating A with ParamsBase ... nothing can be changed
a.params.p1: True
a.params.p2: 99
Checking if p1 has default value: True

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

metaparams-1.0.2.zip (14.8 kB view details)

Uploaded Source

File details

Details for the file metaparams-1.0.2.zip.

File metadata

  • Download URL: metaparams-1.0.2.zip
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for metaparams-1.0.2.zip
Algorithm Hash digest
SHA256 ced966921b121745f9e1ad094160b0f57f110bfb7183116bff500e2000efd39d
MD5 54588704f2883699de3fed5e522cf167
BLAKE2b-256 abde191044087059d7a0caf4543894cbe15936be477c5bc2521665abc7631064

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