From ebb0f96e0e062f54e2741376b2b607bd10442a78 Mon Sep 17 00:00:00 2001 From: obamwonyi Date: Sat, 13 Apr 2024 13:34:53 +0100 Subject: [PATCH] Proper deserialization was implemented --- main.py | 33 +-- requirements.txt | 2 + run.sh | 14 +- src/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 186 bytes src/__pycache__/mine.cpython-310.pyc | Bin 0 -> 798 bytes src/__pycache__/transaction.cpython-310.pyc | Bin 0 -> 2148 bytes src/__pycache__/validation.cpython-310.pyc | Bin 0 -> 991 bytes src/mine.py | 6 +- src/transaction.py | 32 ++- src/validation.py | 4 +- .../INSTALLER | 1 + .../LICENSE | 21 ++ .../METADATA | 153 ++++++++++++++ .../RECORD | 11 + .../REQUESTED | 0 .../WHEEL | 4 + .../marshmallow_oneofschema/__init__.py | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 289 bytes .../__pycache__/one_of_schema.cpython-310.pyc | Bin 0 -> 5643 bytes .../marshmallow_oneofschema/one_of_schema.py | 193 ++++++++++++++++++ .../marshmallow_oneofschema/py.typed | 0 venv/pyvenv.cfg | 2 +- 22 files changed, 449 insertions(+), 28 deletions(-) create mode 100644 requirements.txt create mode 100644 src/__pycache__/__init__.cpython-310.pyc create mode 100644 src/__pycache__/mine.cpython-310.pyc create mode 100644 src/__pycache__/transaction.cpython-310.pyc create mode 100644 src/__pycache__/validation.cpython-310.pyc create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/INSTALLER create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/LICENSE create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/METADATA create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/RECORD create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/REQUESTED create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/WHEEL create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema/__init__.py create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema/__pycache__/one_of_schema.cpython-310.pyc create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema/one_of_schema.py create mode 100644 venv/lib/python3.10/site-packages/marshmallow_oneofschema/py.typed diff --git a/main.py b/main.py index 015f1d8..0a9793e 100644 --- a/main.py +++ b/main.py @@ -1,36 +1,43 @@ import os import asyncio +# TODO: replace json with a serializer +import json from src.transaction import Transaction, TransactionSchema from src.validation import validate_transactions +from marshmallow import ValidationError from src.mine import Mine -async def main() -> None: - """ - This will be responsible for kick-starting the mining process - :return: None - """ - # Read and deserialize transactions from mempool directory +async def main(): + # Step 1: Read and deserialize transactions from the mempool directory transactions = [] + errors = 0 for filename in os.listdir("mempool"): filepath = os.path.join("mempool", filename) with open(filepath, "r") as file: json_data = file.read() + # TODO: This would be reimplemented after I fix deserizlizing with marshmallow transaction_schema = TransactionSchema() try: - transaction = transaction_schema.load(json_data) + transaction = transaction_schema.load(json.loads(json_data)) transactions.append(transaction) - except Exception as e: - print(f"Error deserializing transaction {filename}: {e}") - - # Validate transactions asynchronously + print(f"Deserialized transaction from {filename}") + except ValidationError as e: + errors = errors + 1 + print(f"Error deserializing transaction {filename}:") + print(e.messages) + + print(f"Total transactions deserialized: {len(transactions)}") + print(f"Total failed transactions:{errors}") + + # Step 2: Validate transactions asynchronously valid_transactions = await validate_transactions(transactions) - # Mine the block + # Step 3: Mine the block block_data = mine_block(valid_transactions) + # Step 4: Write the block data to the output.txt file with open("output.txt", "w") as output_file: output_file.write(block_data) - if __name__ == "__main__": asyncio.run(main()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d2703fd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +marshmallow==3.21.1 +packaging==24.0 diff --git a/run.sh b/run.sh index 1b6ee8f..2faabd9 100755 --- a/run.sh +++ b/run.sh @@ -1,13 +1,13 @@ #!/bin/bash -# Create a virtual environment -python3 -m venv venv +# # Create a virtual environment +# python3 -m venv venv -# Activate the virtual environment -source venv/bin/activate +# # Activate the virtual environment +# source venv/bin/activate -# Install project dependencies -pip install -r requirements.txt +# # Install project dependencies +# pip install -r requirements.txt # Run the mine_block.py script -python3 src/mine_block.py \ No newline at end of file +python3 main.py \ No newline at end of file diff --git a/src/__pycache__/__init__.cpython-310.pyc b/src/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca4af977406e4041fdfeed244386d145d7d1396c GIT binary patch literal 186 zcmd1j<>g`kf){gz(m?cM5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;x_)enx(7s(xN- zNqK5wS!$8KOKNd;Nq&L8UQ%XBa(-rBd~s=RZfa3{ep-BTeoCr7h|o>WNX*Ge%}Y{T69V%6$CLawCFCbwx)QL*ZZ`vwN8x=w_4t4m!4~X73@46&&rSi zl<&yR$-UdZb2pM4>e&A=VOh#W3%+egP7 opbz%}_rUkS^hrzyQR}-H()QblM_LY(n*NIo=u6D@49tN20kyKxeE&m;5DPIdSI3i7Iy{>5%MY-Re@6tL!S*S1y;`Zi~Qp_UrxGpFSafp->+l z2)ppB84yMo%}7oonmdt`yOB%DSA;pteN33k>6sgOAbYFL3EkbM?_99Y>0Ib=f7=I>s#*}F;OQqwiOjwE*_2GiB3%~jr z2qzI`Byza>v&SfNey35R#``rssPQ52%?tY$b0HGXbbpZi==+tfBH2HuCY1cqN=VM8 z=WP?lagpRaj!i3$^OCJHo2o^u(Ovp6jopCH*u=Si0F;*jq=`0&9;JLN%=AD6|6m?)V}v`h+>q*|24czGfl z;0q7*PX|ayI<)%w)M{?Pa#=pVf%$V_@h?)2P=ve!z=>KlVA?gl1ALdePrRp4asaIp z^rz0G#`rM0#*s7PrjUv2C@l^#491&NbslvyS2c9UvJ?4m-c5ORoa-QPZ%y=x((C8M&i9A%bgdmcppC=0**KXpQ=mfp@ zoYOaI+f~tx|8G7W-MO`}Z8ZnbCluUn6J}+)&;r`S>#(zY6$v6>+#^v~1mr6?ho_Y9 zA-QZk6=$pNZBXEPn}e$A26R9jr$;5~ZlH*X+ry<2~DYmiAKpu1X zIsEE1AZxlNFDmSAtUaJEBY-2Fjy(B3Sji8N>>$Ckj2iM?H895;vymgmU^E36*V~f`;+U0b9Lov1z6}n{8OEis!-d47J=f-O zI%=ABo=7#%q4}4`5;IV>JBu$S#iCyUkI30|w>dH4C)LyUDFriy?Q%f+PCw{(`oVVV EKMl0tUH||9 literal 0 HcmV?d00001 diff --git a/src/__pycache__/validation.cpython-310.pyc b/src/__pycache__/validation.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..834e45a12b4bd6a125105327db378597ae58d5a2 GIT binary patch literal 991 zcmZ`&L2DE-6i%`;v+K4MSyVg*ytrsPQalwA4?XCm7X_hIhU_G}8#|j!lWc3tELbWY z^)Kkr-{HT=)r0sKJo%E{(kW;lk9;rhz2tpgqBl1B2*&+icgJr!2>lG8J-~;a!?X{; zaKv$i_7Nunj|uPa$(|u0~jg`2(iSz?|cl zL(abRDU8=sY3X>bN+-3Vur|WhT3I=&1RZNbk69%-b5czxiy6)^Wm$}mc&BED&1lQL zLs=VAr|C#s77~1!wY=*N9cf)f&)#=5#D1++#{@c}`BUUmJrlVS?nJO-Ve(yJ51p>_ zt&w!4ma4Gx*-V&1kBd@skq5I`PFYn6H4&TJkGG#}>JgirXmu)cYs&nxF|D@hQ-6B} zMbWxIINuU588U&pYs_}Rk-&`19>C%pPtXE4XcxU*TM&mDa)B3}27kp(=Nrc8D0So= z;LqqKDEk5}5{OS-(x4`}AR+63EXX2jGV`!WA&bN;+N7W{Ir|h@nlLvNhBC!Lsh~E6 z7MI+%Ik*3j#)38w-|Epm0twu7RU*`tDspjMrb=43lxdhoE_}x7S}5+j%$}-JYM(9d z<~wJy9(MhD`w+htqYB6Dq4mVQ_x&q}A6#is!26q5&aQlIHLUMRTg1?-mtj(1-rxC` zdUhSQ>^(5#Lz4Ay53l1}Bq0Nm;64T)F$36yetMxs5? literal 0 HcmV?d00001 diff --git a/src/mine.py b/src/mine.py index b266170..c654d66 100644 --- a/src/mine.py +++ b/src/mine.py @@ -11,7 +11,9 @@ def mine_block(valid_transactions) -> str: :param valid_transactions: all the validated transactions :return: str """ + # TODO: implement block mining here + block_data = "Block header\nCoinbase transaction\n" - for transaction in valid_transactions: - block_data += f"{transaction.txid}\n" + for tx in valid_transactions: + block_data += f"{tx.txid}\n" return block_data diff --git a/src/transaction.py b/src/transaction.py index 063f33c..8926044 100644 --- a/src/transaction.py +++ b/src/transaction.py @@ -1,10 +1,36 @@ from marshmallow import Schema, fields, post_load +class PrevOutSchema(Schema): + scriptpubkey = fields.Str(required=True) + scriptpubkey_asm = fields.Str(required=True) + scriptpubkey_type = fields.Str(required=True) + scriptpubkey_address = fields.Str(required=True) + value = fields.Int(required=True) + +class VinSchema(Schema): + txid = fields.Str(required=True) + vout = fields.Int(required=True) + prevout = fields.Nested(PrevOutSchema, required=True) + scriptsig = fields.Str(required=True) + scriptsig_asm = fields.Str(required=True) + witness = fields.List(fields.Str(), required=False) + is_coinbase = fields.Bool(required=True) + sequence = fields.Int(required=True) + inner_redeemscript_asm = fields.Str(required=False) + inner_witnessscript_asm = fields.Str(required=False) + +class VoutSchema(Schema): + scriptpubkey = fields.Str(required=True) + scriptpubkey_asm = fields.Str(required=True) + scriptpubkey_type = fields.Str(required=True) + scriptpubkey_address = fields.Str(required=False) + value = fields.Int(required=True) + class TransactionSchema(Schema): version = fields.Int(required=True) locktime = fields.Int(required=True) - vin = fields.List(fields.Dict(), required=True) - vout = fields.List(fields.Dict(), required=True) + vin = fields.List(fields.Nested(VinSchema), required=True) + vout = fields.List(fields.Nested(VoutSchema), required=True) @post_load def make_transaction(self, data, **kwargs): @@ -16,6 +42,6 @@ class Transaction: """ def __init__(self, version, locktime, vin, vout) -> None: self.version = version - self.locktime = version + self.locktime = locktime self.vin = vin self.vout = vout diff --git a/src/validation.py b/src/validation.py index a0d291b..23b5287 100644 --- a/src/validation.py +++ b/src/validation.py @@ -7,7 +7,7 @@ async def validate_transaction(transaction) -> bool: :param transaction: a transaction to be validated :return: bool """ - pass + async def validate_transactions(transactions) -> list: """ @@ -27,5 +27,5 @@ async def validate_transactions(transactions) -> list: for tx, is_valid in zip(transactions, validation_results): if is_valid: valid_transactions.append(tx) - + return valid_transactions diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/INSTALLER b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/LICENSE b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/LICENSE new file mode 100644 index 0000000..d0c0544 --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/LICENSE @@ -0,0 +1,21 @@ +Copyright 2016-2017 Maxim Kulkin +Copyright 2018 Alex Rothberg and contributors +Copyright 2024 Steven Loria and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/METADATA b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/METADATA new file mode 100644 index 0000000..f770ce3 --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/METADATA @@ -0,0 +1,153 @@ +Metadata-Version: 2.1 +Name: marshmallow-oneofschema +Version: 3.1.1 +Summary: marshmallow multiplexing schema +Author-email: Maxim Kulkin +Maintainer-email: Steven Loria +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Requires-Dist: marshmallow>=3.0.0,<4.0.0 +Requires-Dist: marshmallow-oneofschema[tests] ; extra == "dev" +Requires-Dist: tox ; extra == "dev" +Requires-Dist: pre-commit~=3.5 ; extra == "dev" +Requires-Dist: pytest ; extra == "tests" +Project-URL: Funding, https://opencollective.com/marshmallow +Project-URL: Issues, https://github.com/marshmallow-code/marshmallow-oneofschema/issues +Project-URL: Source, https://github.com/marshmallow-code/marshmallow-oneofschema +Provides-Extra: dev +Provides-Extra: tests + +======================= +marshmallow-oneofschema +======================= + +.. image:: https://github.com/marshmallow-code/marshmallow-oneofschema/actions/workflows/build-release.yml/badge.svg + :target: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml + :alt: Build Status + +.. image:: https://badgen.net/badge/marshmallow/3 + :target: https://marshmallow.readthedocs.io/en/latest/upgrading.html + :alt: marshmallow 3 compatible + +An extension to marshmallow to support schema (de)multiplexing. + +marshmallow is a fantastic library for serialization and deserialization of data. +For more on that project see its `GitHub `_ +page or its `Documentation `_. + +This library adds a special kind of schema that actually multiplexes other schemas +based on object type. When serializing values, it uses get_obj_type() method +to get object type name. Then it uses ``type_schemas`` name-to-Schema mapping +to get schema for that particular object type, serializes object using that +schema and adds an extra field with name of object type. Deserialization is reverse. + +Installing +---------- + +:: + + $ pip install marshmallow-oneofschema + +Example +------- + +The code below demonstrates how to set up a polymorphic schema. For the full context check out the tests. +Once setup the schema should act like any other schema. If it does not then please file an Issue. + +.. code:: python + + import marshmallow + import marshmallow.fields + from marshmallow_oneofschema import OneOfSchema + + + class Foo: + def __init__(self, foo): + self.foo = foo + + + class Bar: + def __init__(self, bar): + self.bar = bar + + + class FooSchema(marshmallow.Schema): + foo = marshmallow.fields.String(required=True) + + @marshmallow.post_load + def make_foo(self, data, **kwargs): + return Foo(**data) + + + class BarSchema(marshmallow.Schema): + bar = marshmallow.fields.Integer(required=True) + + @marshmallow.post_load + def make_bar(self, data, **kwargs): + return Bar(**data) + + + class MyUberSchema(OneOfSchema): + type_schemas = {"foo": FooSchema, "bar": BarSchema} + + def get_obj_type(self, obj): + if isinstance(obj, Foo): + return "foo" + elif isinstance(obj, Bar): + return "bar" + else: + raise Exception("Unknown object type: {}".format(obj.__class__.__name__)) + + + MyUberSchema().dump([Foo(foo="hello"), Bar(bar=123)], many=True) + # => [{'type': 'foo', 'foo': 'hello'}, {'type': 'bar', 'bar': 123}] + + MyUberSchema().load( + [{"type": "foo", "foo": "hello"}, {"type": "bar", "bar": 123}], many=True + ) + # => [Foo('hello'), Bar(123)] + +By default get_obj_type() returns obj.__class__.__name__, so you can just reuse that +to save some typing: + +.. code:: python + + class MyUberSchema(OneOfSchema): + type_schemas = {"Foo": FooSchema, "Bar": BarSchema} + +You can customize type field with `type_field` class property: + +.. code:: python + + class MyUberSchema(OneOfSchema): + type_field = "object_type" + type_schemas = {"Foo": FooSchema, "Bar": BarSchema} + + + MyUberSchema().dump([Foo(foo="hello"), Bar(bar=123)], many=True) + # => [{'object_type': 'Foo', 'foo': 'hello'}, {'object_type': 'Bar', 'bar': 123}] + +You can use resulting schema everywhere marshmallow.Schema can be used, e.g. + +.. code:: python + + import marshmallow as m + import marshmallow.fields as f + + + class MyOtherSchema(m.Schema): + items = f.List(f.Nested(MyUberSchema)) + +License +------- + +MIT licensed. See the bundled `LICENSE `_ file for more details. + diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/RECORD b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/RECORD new file mode 100644 index 0000000..727b5e4 --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/RECORD @@ -0,0 +1,11 @@ +marshmallow_oneofschema-3.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +marshmallow_oneofschema-3.1.1.dist-info/LICENSE,sha256=Dj6i54GCxVk8glcTykJvh2Mga2HVVWw0_0cARUXh_uk,1148 +marshmallow_oneofschema-3.1.1.dist-info/METADATA,sha256=cPVqGW5WZduc5r9TBHC-fxFMu8Axv0XO1cd9LIuLZCI,5018 +marshmallow_oneofschema-3.1.1.dist-info/RECORD,, +marshmallow_oneofschema-3.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +marshmallow_oneofschema-3.1.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +marshmallow_oneofschema/__init__.py,sha256=KQjXt0W26CH8CvBBTA0YFEMsIHwR9_oMfBGppTnoTlI,47 +marshmallow_oneofschema/__pycache__/__init__.cpython-310.pyc,, +marshmallow_oneofschema/__pycache__/one_of_schema.cpython-310.pyc,, +marshmallow_oneofschema/one_of_schema.py,sha256=cdaUaBSYXhwN7vusKCJFr9N0D_iyKIAmEsfzdBnISYM,6722 +marshmallow_oneofschema/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/REQUESTED b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/WHEEL b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema-3.1.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema/__init__.py b/venv/lib/python3.10/site-packages/marshmallow_oneofschema/__init__.py new file mode 100644 index 0000000..62413dd --- /dev/null +++ b/venv/lib/python3.10/site-packages/marshmallow_oneofschema/__init__.py @@ -0,0 +1 @@ +from .one_of_schema import OneOfSchema # noqa diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema/__pycache__/__init__.cpython-310.pyc b/venv/lib/python3.10/site-packages/marshmallow_oneofschema/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49e4e135c2ed190bece3d384943861dd0ef251be GIT binary patch literal 289 zcmYjMF;2uV5VQjY0!6xtKcqBhdx6efVaJAUm+KEzcbujQEM4Vfv&_MhjVyl=A7?* z=a6x|UeWN|{&uPJ?#r6?FX|M3COX$~$W=6f7O<|iNoT#wditi`Gd2yTy{`pEV1A_q zCf5&)O*3HYTC?;YJfYob>Y26P-r+qzJN1#@4Ff+33#%mq@oJI$)2j*2RC0lmr=2id9V?9_17STVW`b+4)6r4qW zAt+;e=d$XD5&y80@6E5h}zY|ED%&qi*%waeRyo9y>_%e}Y5BUf?(<>4@lw%vz* zcfjSU8z$~RLeVx)JUro%_)635@nk0sl)@yY!J;}h@_W#Emvl~^|BN2=^7YEkl*FYZ zzLam(?fLyaW-aO)Z>5d^+j>2)#;*Xv-yq&k~Tm#QToP;d|1p60$4F} z`J+Vm?s;0$dAAetZs6{P$&OkTnYCydrQ5^TH@hJa0wvZfDi)#PN&}3DQ^#L+&*anAQKTFTS__ zEnmDyKZc+m?W}&RKX=he&lhs12Y|(Ut^C%EvV4t2F=biVT2BNVvLg6{K`3}|?XDQ` z=Fvp7$?L_(`ms#BZtUmqqG9@x!Fv9E?qQy>!4UWUs(bO`{XJi7%bDfSGlC}r5h*8J zyhzf8X>E`jV*rC9t%t}W4U6a z0u`Sh!!4P087^49LT1fvxB9#U_5ca2>m-TMap#j~kI_pW4hWl>h0)w$2f-IcGV!A} zC+M%zI!+KI;j#bKdY@Y(@1CFwEB+2$w6ha*NyI))Ir|fSD7ky%QJeQENv$kzME9e3 z?->1FaWBYa_X3vNSJB)o!1S2^nyp~a>#ux*9k0L#*OqrU;&HjTN|s*1%C5b6`K{)s zs|b{6e;j9%1-<58d&m9c^JVfbT%&BVI&tM#(P-5@5}=JjfKFFj=pB8UyY1t6;I=`c z?KnzA+*Ju=Orpg5M6yUQ$O;q6q;!)rGi?w|8YMZ4ZtW|RNuDIc*m;UjLG{^~KKml> zbCK+~lwfAk;_qg)B0}3b68q#w*9^z6a7YJD%67F~DjnGHqhBjFkW-dNYMdm{U_cb* zD(g0}yKWb$Z##U51V&Q%@~8gY;uB#Wv`~zcJx{TT=VgxPkr6x(w@t!vX5is(G*QK3 zzWvMEPTb>b5l{BGkMyyIymCK@`)jSOFlonO?x24h zXJPJP($Z?0nSm{46@@Pa#O(CZwI_Hle#kSUANQMvC}W$MNe^aaYE@~Z{G2y68n2Vd zrlU7-OTn^cG+2$9YMc?$~r96QseLJ&&$CF0 zA+tEWI>@XFaspn|oLPO`8IM_cH#5TEQO4q|r0!=1f7G7!xk>B0jalSHG$!0^vLzg6 zSwq*^Je$K`4L#@g`cu=ysBW@39K%Kt45S1Qs1N#p1gajYQspr$5WiVC6c)b5MXDj_ zDCA&ag@iNob``+$yKGlq(n8ijxWU5)JZeI&l$Ip?0~sSVC*$x+DX|W8aWO4LdRjUl zWLdlRp_7zTypM(2fk9}%y$WH9UW`JP;|l(@F*6gl;8`0pRe=k5x@q6Z>@nR8&(5Sk z#hsJ`hp%iza?tO`B00(#6n`|B*_3doawja@gg5Ir3%ny~f-E7(6k-ldRynE=1kspi z(p@XJWM(5I{Uj0Mbs9Q_2Kb_2&XKW9S3g9PIbd!T)LFHVa55`rP4QzAq*y!(cX1Bg z4i5PPG!^DBU7us-(^|=74Yr^!=u5i8Dirvqi@sKf{>I2rX{$FKznj^Eyi}Mvo$yT? zoD#r!Pyz)$2*AeKc>w_!3Jhl{v_}T$;C&V52>lM+2B@&daPycJ$|L)p7HuHR&HbC> zFmE8tOHW9@eQ2f6g?RMNQHUqbm{8sZp;SjTPz2zX)&LVdH2@Pe�_4mB*xVOU?GX z0;yoO)JYY1PMYz-t)m%J8`>O#sQhD!x9G$K9kH|=7$B8;S_i3^L@IB>aN;sG>S_sB z&9bt%I6JuuZlT7)NM~}1;WWM`(A9Y~ znTg!o6Bnp|95t)Y-b_nNTK-IGe~BbEvcIrZ!m#A}SO#-U zWUv;HPf`X&ZKf6|$^u0>sk2)-tR^*3lr^O&XSc2>%1(j4zULczcso# z4m$BR?)?>qq>Bm&%F!zzCkIIi6!lCu8^9J3nEp)H^`|Obm4HBuEtm`X%lZt75yTK^ zM9(V5jvb)M8|fJpDV9oZl=Jj5A$RrlagWZimcK06>!c2ee2cSjy6-G52(y za`dy|LXoQ{!p%jMcCw1+_2OXAMa`epJnsR%!R2oNNO)clw>>ZSY=f3aIV!V|O;Czv z_U-(uS7yjWWTlM=?}wR5ZdV@9PI;amMRESJB%wzoJcSjNx+vM?J0}NyXK+h4+RWeUy5X$VoF~&ehxm Q?@); [{'type': 'foo', 'foo': 'hello'}, {'type': 'bar', 'bar': 123}] + + You can control type field name added to serialized object representation by + setting `type_field` class property. + """ + + type_field = "type" + type_field_remove = True + type_schemas: typing.Mapping[str, typing.Union[typing.Type[Schema], Schema]] = {} + + def get_obj_type(self, obj): + """Returns name of the schema during dump() calls, given the object + being dumped.""" + return obj.__class__.__name__ + + def get_data_type(self, data): + """Returns name of the schema during load() calls, given the data being + loaded. Defaults to looking up `type_field` in the data.""" + data_type = data.get(self.type_field) + if self.type_field in data and self.type_field_remove: + data.pop(self.type_field) + return data_type + + def dump(self, obj, *, many=None, **kwargs): + errors = {} + result_data = [] + result_errors = {} + many = self.many if many is None else bool(many) + if not many: + result = result_data = self._dump(obj, **kwargs) + else: + for idx, o in enumerate(obj): + try: + result = self._dump(o, **kwargs) + result_data.append(result) + except ValidationError as error: + result_errors[idx] = error.normalized_messages() + result_data.append(error.valid_data) + + result = result_data + errors = result_errors + + if not errors: + return result + else: + exc = ValidationError(errors, data=obj, valid_data=result) + raise exc + + def _dump(self, obj, *, update_fields=True, **kwargs): + obj_type = self.get_obj_type(obj) + if obj_type is None: + return ( + None, + {"_schema": "Unknown object class: %s" % obj.__class__.__name__}, + ) + + type_schema = self.type_schemas.get(obj_type) + if not type_schema: + return None, {"_schema": "Unsupported object type: %s" % obj_type} + + schema = type_schema if isinstance(type_schema, Schema) else type_schema() + + schema.context.update(getattr(self, "context", {})) + + result = schema.dump(obj, many=False, **kwargs) + if result is not None: + result[self.type_field] = obj_type + return result + + def load(self, data, *, many=None, partial=None, unknown=None, **kwargs): + errors = {} + result_data = [] + result_errors = {} + many = self.many if many is None else bool(many) + if partial is None: + partial = self.partial + if not many: + try: + result = result_data = self._load( + data, partial=partial, unknown=unknown, **kwargs + ) + # result_data.append(result) + except ValidationError as error: + result_errors = error.normalized_messages() + result_data.append(error.valid_data) + else: + for idx, item in enumerate(data): + try: + result = self._load(item, partial=partial, **kwargs) + result_data.append(result) + except ValidationError as error: + result_errors[idx] = error.normalized_messages() + result_data.append(error.valid_data) + + result = result_data + errors = result_errors + + if not errors: + return result + else: + exc = ValidationError(errors, data=data, valid_data=result) + raise exc + + def _load(self, data, *, partial=None, unknown=None, **kwargs): + if not isinstance(data, dict): + raise ValidationError({"_schema": "Invalid data type: %s" % data}) + + data = dict(data) + unknown = unknown or self.unknown + data_type = self.get_data_type(data) + + if data_type is None: + raise ValidationError( + {self.type_field: ["Missing data for required field."]} + ) + + try: + type_schema = self.type_schemas.get(data_type) + except TypeError as error: + # data_type could be unhashable + raise ValidationError( + {self.type_field: ["Invalid value: %s" % data_type]} + ) from error + if not type_schema: + raise ValidationError( + {self.type_field: ["Unsupported value: %s" % data_type]} + ) + + schema = type_schema if isinstance(type_schema, Schema) else type_schema() + + schema.context.update(getattr(self, "context", {})) + + return schema.load(data, many=False, partial=partial, unknown=unknown, **kwargs) + + def validate(self, data, *, many=None, partial=None): + try: + self.load(data, many=many, partial=partial) + except ValidationError as ve: + return ve.messages + return {} diff --git a/venv/lib/python3.10/site-packages/marshmallow_oneofschema/py.typed b/venv/lib/python3.10/site-packages/marshmallow_oneofschema/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg index 0537ffc..6d66b89 100644 --- a/venv/pyvenv.cfg +++ b/venv/pyvenv.cfg @@ -1,3 +1,3 @@ -home = /usr/bin +home = /home/netweaver/Desktop/.bitcoin_summer_of_code/code-challenge-2024-obamwonyi/venv/bin include-system-site-packages = false version = 3.10.12