{"id":15579021,"url":"https://github.com/dapper91/paxb","last_synced_at":"2026-01-31T08:33:17.264Z","repository":{"id":57463132,"uuid":"200107849","full_name":"dapper91/paxb","owner":"dapper91","description":"Python Architecture for XML Binding","archived":false,"fork":false,"pushed_at":"2019-10-10T16:24:55.000Z","size":69,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-28T15:49:23.220Z","etag":null,"topics":["binding","deserialization","json","mapping","marshalling","python","serialization","unmarshalling","xml"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dapper91.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","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":"2019-08-01T19:26:03.000Z","updated_at":"2023-03-23T07:36:27.000Z","dependencies_parsed_at":"2022-09-12T13:22:35.104Z","dependency_job_id":null,"html_url":"https://github.com/dapper91/paxb","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/dapper91/paxb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapper91%2Fpaxb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapper91%2Fpaxb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapper91%2Fpaxb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapper91%2Fpaxb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dapper91","download_url":"https://codeload.github.com/dapper91/paxb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapper91%2Fpaxb/sbom","scorecard":{"id":322224,"data":{"date":"2025-08-11","repo":{"name":"github.com/dapper91/paxb","commit":"3e7c001227cc0e62b772813862eee9c8fd43ce10"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 0/9 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: The Unlicense: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T01:39:27.181Z","repository_id":57463132,"created_at":"2025-08-18T01:39:27.182Z","updated_at":"2025-08-18T01:39:27.182Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28935417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T07:49:44.436Z","status":"ssl_error","status_checked_at":"2026-01-31T07:49:34.274Z","response_time":128,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["binding","deserialization","json","mapping","marshalling","python","serialization","unmarshalling","xml"],"created_at":"2024-10-02T19:13:37.126Z","updated_at":"2026-01-31T08:33:17.240Z","avatar_url":"https://github.com/dapper91.png","language":"Python","readme":"====\npaxb\n====\n\n.. image:: https://travis-ci.org/dapper91/paxb.svg?branch=master\n    :target: https://travis-ci.org/dapper91/paxb\n    :alt: Build status\n.. image:: https://img.shields.io/pypi/l/paxb.svg\n    :target: https://pypi.org/project/paxb\n    :alt: License\n.. image:: https://img.shields.io/pypi/pyversions/paxb.svg\n    :target: https://pypi.org/project/paxb\n    :alt: Supported Python versions\n.. image:: https://codecov.io/gh/dapper91/paxb/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/dapper91/paxb\n    :alt: Code coverage\n\n\nPython Architecture for XML Binding\n-----------------------------------\n\n``paxb`` is a library that provides an API for mapping between XML documents and Python objects.\n\n``paxb`` library implements the following functionality:\n\n- Deserialize XML documents to Python objects\n- Validate deserialized data\n- Access and update Python object fields\n- Serialize Python objects to XML documents\n\n``paxb`` provides an efficient way of mapping between an XML document and a Python object. Using ``paxb``\ndevelopers can write less boilerplate code emphasizing on application domain logic.\n\nSince ``paxb`` based on `attrs \u003chttps://www.attrs.org/en/stable/index.html\u003e`_ library ``paxb`` and ``attrs``\nAPI can be mixed together.\n\n\nInstallation\n------------\n\nYou can install paxb with pip:\n\n.. code-block:: console\n\n    $ pip install paxb\n\n\nRequirements\n------------\n\n- `attrs \u003chttps://www.attrs.org/en/stable/index.html\u003e`_\n\n\nDocumentation\n-------------\n\nDocumentation is available at `Read the Docs \u003chttps://paxb.readthedocs.io/en/latest/\u003e`_.\n\n\nQuick start\n===========\n\nSuppose you have an xml document ``user.xml``:\n\n.. code-block:: xml\n\n    \u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n    \u003cdoc:envelope xmlns=\"http://www.test.org\"\n                  xmlns:doc=\"http://www.test1.org\"\u003e\n        \u003cdoc:user name=\"Alex\" surname=\"Ivanov\" age=\"26\"\u003e\n\n            \u003cdoc:birthdate year=\"1992\" month=\"06\" day=\"14\"/\u003e\n\n            \u003cdoc:contacts\u003e\n                \u003cdoc:phone\u003e+79204563539\u003c/doc:phone\u003e\n                \u003cdoc:email\u003ealex@gmail.com\u003c/doc:email\u003e\n                \u003cdoc:email\u003ealex@mail.ru\u003c/doc:email\u003e\n            \u003c/doc:contacts\u003e\n\n            \u003cdoc:documents\u003e\n                \u003cdoc:passport series=\"3127\" number=\"836815\"/\u003e\n            \u003c/doc:documents\u003e\n\n            \u003cdata:occupations xmlns:data=\"http://www.test2.org\"\u003e\n                \u003cdata:occupation title=\"yandex\"\u003e\n                    \u003cdata:address\u003eMoscow\u003c/data:address\u003e\n                    \u003cdata:employees\u003e8854\u003c/data:employees\u003e\n                \u003c/data:occupation\u003e\n                \u003cdata:occupation title=\"skbkontur\"\u003e\n                    \u003cdata:address\u003eYekaterinburg\u003c/data:address\u003e\n                    \u003cdata:employees\u003e7742\u003c/data:employees\u003e\n                \u003c/data:occupation\u003e\n            \u003c/data:occupations\u003e\n\n        \u003c/doc:user\u003e\n    \u003c/doc:envelope\u003e\n\n\nTo deserialize the document you could use `xml \u003chttps://docs.python.org/3/library/xml.html\u003e`_ library api to parse\nthe document and then access and modify the parsed xml DOM manually. Such an imperative code has a lot of boilerplate\noperations that takes a lot of time and can lead to bugs. Instead you can use ``paxb`` api to write a declarative\nstyle code. All you need to describe field mappings and types, ``paxb`` will serialize and deserialize data for you:\n\n.. code-block:: python\n\n    import json\n    import re\n    from datetime import date\n\n    import attr\n    import paxb as pb\n\n\n    @pb.model(name='occupation', ns='data', ns_map={'data': 'http://www.test2.org'})\n    class Occupation:\n        title = pb.attr()\n        address = pb.field()\n        employees = pb.field(converter=int)\n\n\n    @pb.model(name='user', ns='doc', ns_map={'doc': 'http://www.test1.org'})\n    class User:\n        name = pb.attr()\n        surname = pb.attr()\n        age = pb.attr(converter=int)\n\n        birth_year = pb.wrap('birthdate', pb.attr('year', converter=int))\n        birth_month = pb.wrap('birthdate', pb.attr('month', converter=int))\n        birth_day = pb.wrap('birthdate', pb.attr('day', converter=int))\n\n        @property\n        def birthdate(self):\n            return date(year=self.birth_year, month=self.birth_month, day=self.birth_day)\n\n        @birthdate.setter\n        def birthdate(self, value):\n            self.birth_year = value.year\n            self.birth_month = value.month\n            self.birth_day = value.day\n\n        phone = pb.wrap('contacts', pb.field())\n        emails = pb.wrap('contacts', pb.as_list(pb.field(name='email')))\n\n        passport_series = pb.wrap('documents/passport', pb.attr('series'))\n        passport_number = pb.wrap('documents/passport', pb.attr('number'))\n\n        occupations = pb.wrap(\n            'occupations', pb.lst(pb.nested(Occupation)), ns='data', ns_map={'data': 'http://www.test2.org'}\n        )\n\n        citizenship = pb.field(default='RU')\n\n        @phone.validator\n        def check(self, attribute, value):\n            if not re.match(r'\\+\\d{11,13}', value):\n                raise ValueError(\"phone number is incorrect\")\n\n\n    with open('user.xml') as file:\n        xml = file.read()\n\n\nThen the deserialized object can be modified and serialized back to xml document or converted to json format:\n\n.. code-block:: python\n\n    try:\n        user = pb.from_xml(User, xml, envelope='doc:envelope', ns_map={'doc': 'http://www.test1.org'})\n        user.birthdate = user.birthdate.replace(year=1993)\n\n        with open('user.json') as file:\n            json.dump(attr.asdict(user), file)\n\n    except (pb.exc.DeserializationError, ValueError) as e:\n        print(f\"deserialization error: {e}\")\n\n\n``user.json``:\n\n.. code-block:: json\n\n    {\n        \"age\": 26,\n        \"birth_day\": 14,\n        \"birth_month\": 6,\n        \"birth_year\": 1993,\n        \"citizenship\": \"RU\",\n        \"emails\": [\"alex@gmail.com\", \"alex@mail.ru\"],\n        \"name\": \"Alexey\",\n        \"occupations\": [\n            {\n                \"address\": \"Moscow\",\n                \"employees\": 8854,\n                \"title\": \"yandex\"\n            },\n            {\n                \"address\": \"Yekaterinburg\",\n                \"employees\": 7742,\n                \"title\": \"skbkontur\"\n            }\n        ],\n        \"passport_number\": \"836815\",\n        \"passport_series\": \"3127\",\n        \"phone\": \"+79204563539\",\n        \"surname\": \"Ivanov\"\n    }\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapper91%2Fpaxb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdapper91%2Fpaxb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapper91%2Fpaxb/lists"}