{"id":15896204,"url":"https://github.com/numberoverzero/declare","last_synced_at":"2025-07-18T04:36:44.865Z","repository":{"id":21491110,"uuid":"24809984","full_name":"numberoverzero/declare","owner":"numberoverzero","description":"Python scaffolding for declarative resource modeling","archived":false,"fork":false,"pushed_at":"2017-10-08T01:47:07.000Z","size":63,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T18:32:20.524Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/numberoverzero.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-05T06:30:29.000Z","updated_at":"2017-06-23T05:48:52.000Z","dependencies_parsed_at":"2022-08-21T15:40:48.475Z","dependency_job_id":null,"html_url":"https://github.com/numberoverzero/declare","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/numberoverzero/declare","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fdeclare","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fdeclare/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fdeclare/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fdeclare/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/numberoverzero","download_url":"https://codeload.github.com/numberoverzero/declare/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fdeclare/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265701400,"owners_count":23813751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-06T09:06:51.151Z","updated_at":"2025-07-18T04:36:44.848Z","avatar_url":"https://github.com/numberoverzero.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":".. image:: https://img.shields.io/travis/numberoverzero/declare/master.svg?style=flat-square\n    :target: https://travis-ci.org/numberoverzero/declare\n.. image:: https://img.shields.io/codecov/c/github/numberoverzero/declare/master.svg?style=flat-square\n    :target: https://codecov.io/gh/numberoverzero/declare/branch/master\n.. image:: https://img.shields.io/pypi/v/declare.svg?style=flat-square\n    :target: https://pypi.python.org/pypi/declare\n.. image:: https://img.shields.io/pypi/status/declare.svg?style=flat-square\n    :target: https://pypi.python.org/pypi/declare\n.. image:: https://img.shields.io/github/issues-raw/numberoverzero/declare.svg?style=flat-square\n    :target: https://github.com/numberoverzero/declare/issues\n.. image:: https://img.shields.io/pypi/l/declare.svg?style=flat-square\n    :target: https://github.com/numberoverzero/declare/blob/master/LICENSE\n\nDeclarative scaffolding for frameworks\n\nInstallation\n============\n\n``pip install declare``\n\nGetting Started\n===============\n\nLet's build a quick model for Minecraft blocks::\n\n    from declare import Model, Field, TypeDefinition\n    import json\n\n    # Wire format is json:\n    # {\n    #   \"type\": int     \u003c- maps to enum\n    #   \"position\": str \u003c- packed x:y:z\n    # }\n\n    class BlockType(TypeDefinition):\n        types = {\n            0: \"Grass\",\n            1: \"Stone\",\n            2: \"Diamond\"\n        }\n        def load(self, value, context):\n            return BlockType.types[value]\n\n        def dump(self, value, context):\n            # TODO: index types by value for O(1) lookup\n            for tid, name in BlockType.types.items():\n                if value == name:\n                    return tid\n\n\n    class Position(TypeDefinition):\n        ''' [x, y, z] \u003c--\u003e \"x:y:z\" '''\n        def load(self, value, context):\n            return [int(v) for v in value.split(':')]\n\n        def dump(self, value, context):\n            return ':'.join(str(v) for v in value)\n\n\n    class Block(Model):\n        type = Field(BlockType)\n        position = Field(Position)\n\n        @classmethod\n        def load(cls, wire):\n            fields = cls.Meta.fields_by_model_name\n            engine = cls.Meta.type_engine\n            wire = json.loads(wire)\n            kwargs = {}\n            for name, field in fields.items():\n                kwargs[name] = engine.load(field.typedef, wire[name], {})\n            return cls(**kwargs)\n\n        @classmethod\n        def dump(cls, obj):\n            fields = cls.Meta.fields_by_model_name\n            engine = cls.Meta.type_engine\n            kwargs = {}\n            for name, field in fields.items():\n                kwargs[name] = engine.dump(\n                    field.typedef, getattr(obj, name), {})\n            return json.dumps(kwargs)\n\n\nLet's set up our request handler to use these blocks::\n\n    from bottle import route, request\n\n    @route('/diamond_check')\n    def func():\n        wire = request.json\n        block = Block.load(wire)\n        if block.type == \"Diamond\":\n            return {\"diamond\": True, \"position\": block.position}\n        return {\"diamond\": False}\n\n\nAlternatively, creating a diamond::\n\n    @route('/make_diamond')\n    def func():\n        wire = request.json\n        position = Position.load(wire)\n        block = Block(type=\"Diamond\", position=position)\n        return Block.dump(block)\n\n\nNested Models\n=============\n\nModels are instances of TypeDefinitions, too.  That means models can be used\nas fields, making recursive load/dump easy::\n\n    class List(TypeDefinition):\n        ''' Adapter for lists of objects '''\n        def load(self, value, context):\n            return [self.typedef.load(v, context) for v in value]\n        def dump(self, value, context):\n            return [self.typedef.dump(v, context) for v in value]\n\n\n    class Region(Model):\n        blocks = Field(List(Block))\n\n        @classmethod\n        def load(cls, wire):\n            fields = cls.Meta.fields_by_model_name\n            engine = cls.Meta.type_engine\n            wire = json.loads(wire)\n            kwargs = {}\n            for name, field in fields.items():\n                kwargs[name] = engine.load(field.typedef, wire[name], {})\n            return cls(**kwargs)\n\n        @classmethod\n        def dump(cls, obj):\n            fields = cls.Meta.fields_by_model_name\n            engine = cls.Meta.type_engine\n            kwargs = {}\n            for name, field in fields.items():\n                kwargs[name] = engine.dump(\n                    field.typedef, getattr(obj, name), {})\n            return json.dumps(kwargs)\n\n\nIn fact, the same load/dump code from ``Block`` is usable here, since we're\njust going to be loading/dumping from json.  When the type engine looks up the\nload/dump functions for the ``List(Block)`` type, it will iteratively load/dump\neach block using the Block.load and Block.dump methods.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumberoverzero%2Fdeclare","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnumberoverzero%2Fdeclare","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumberoverzero%2Fdeclare/lists"}