From f2be7a2018257fac45a6ccb948cb8980db8adc99 Mon Sep 17 00:00:00 2001 From: Tim Diekmann <21277928+TimDiekmann@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:34:10 +0100 Subject: [PATCH] Move Python libraries from `hashintel/hash` into labs (#54) --- libs/hash-graph-client/python/.gitattributes | 1 + libs/hash-graph-client/python/.gitignore | 1 + libs/hash-graph-client/python/LICENSE.md | 606 ++++++++ libs/hash-graph-client/python/README.md | 6 + .../python/graph_client/__init__.py | 357 +++++ .../python/graph_client/models.py | 1238 +++++++++++++++ .../python/graph_client/py.typed | 0 .../python/graph_client/schema.py | 13 + libs/hash-graph-client/python/package.json | 25 + libs/hash-graph-client/python/poetry.lock | 1344 +++++++++++++++++ libs/hash-graph-client/python/poetry.toml | 3 + libs/hash-graph-client/python/pyproject.toml | 91 ++ .../python/scripts/aliases.json | 4 + .../python/scripts/codegen.sh | 56 + .../python/scripts/rebase.py | 37 + libs/hash-graph-client/python/turbo.json | 49 + libs/hash-graph-client/python/yarn.lock | 314 ++++ libs/hash-graph-sdk/python/.gitattributes | 2 + libs/hash-graph-sdk/python/LICENSE.md | 606 ++++++++ libs/hash-graph-sdk/python/README.md | 3 + .../python/examples/query_company_entities.py | 24 + .../query_company_entities_limited_axes.py | 35 + .../examples/query_company_entity_type.py | 31 + .../python/graph_sdk/__init__.py | 20 + .../python/graph_sdk/client/__init__.py | 1 + .../python/graph_sdk/client/_compat.py | 10 + .../python/graph_sdk/client/blocking.py | 99 ++ .../python/graph_sdk/client/concurrent.py | 266 ++++ .../python/graph_sdk/filter/__init__.py | 20 + .../python/graph_sdk/filter/base.py | 67 + .../python/graph_sdk/filter/config.json | 51 + .../python/graph_sdk/filter/path.py | 226 +++ .../python/graph_sdk/options.py | 372 +++++ libs/hash-graph-sdk/python/graph_sdk/py.typed | 0 libs/hash-graph-sdk/python/graph_sdk/query.py | 366 +++++ libs/hash-graph-sdk/python/graph_sdk/types.py | 212 +++ libs/hash-graph-sdk/python/graph_sdk/utils.py | 92 ++ libs/hash-graph-sdk/python/package.json | 25 + libs/hash-graph-sdk/python/poetry.lock | 791 ++++++++++ libs/hash-graph-sdk/python/poetry.toml | 3 + libs/hash-graph-sdk/python/pyproject.toml | 90 ++ .../python/scripts/generate_blocking.py | 219 +++ .../python/scripts/generate_filter.py | 618 ++++++++ libs/hash-graph-sdk/python/turbo.json | 56 + libs/hash-graph-types/python/LICENSE.md | 606 ++++++++ libs/hash-graph-types/python/README.md | 3 + .../python/graph_types/__init__.py | 61 + .../graph_types/_annotations/__init__.py | 4 + .../python/graph_types/_annotations/const.py | 68 + .../graph_types/_annotations/require.py | 22 + .../python/graph_types/_schema.py | 205 +++ .../python/graph_types/base.py | 62 + .../python/graph_types/data_type.py | 122 ++ .../python/graph_types/entity_type.py | 123 ++ .../python/graph_types/property_type.py | 115 ++ .../python/graph_types/py.typed | 0 libs/hash-graph-types/python/package.json | 19 + libs/hash-graph-types/python/poetry.lock | 404 +++++ libs/hash-graph-types/python/poetry.toml | 3 + libs/hash-graph-types/python/pyproject.toml | 82 + libs/hash-graph-types/python/turbo.json | 41 + 61 files changed, 10390 insertions(+) create mode 100644 libs/hash-graph-client/python/.gitattributes create mode 100644 libs/hash-graph-client/python/.gitignore create mode 100644 libs/hash-graph-client/python/LICENSE.md create mode 100644 libs/hash-graph-client/python/README.md create mode 100644 libs/hash-graph-client/python/graph_client/__init__.py create mode 100644 libs/hash-graph-client/python/graph_client/models.py create mode 100644 libs/hash-graph-client/python/graph_client/py.typed create mode 100644 libs/hash-graph-client/python/graph_client/schema.py create mode 100644 libs/hash-graph-client/python/package.json create mode 100644 libs/hash-graph-client/python/poetry.lock create mode 100644 libs/hash-graph-client/python/poetry.toml create mode 100644 libs/hash-graph-client/python/pyproject.toml create mode 100644 libs/hash-graph-client/python/scripts/aliases.json create mode 100755 libs/hash-graph-client/python/scripts/codegen.sh create mode 100644 libs/hash-graph-client/python/scripts/rebase.py create mode 100644 libs/hash-graph-client/python/turbo.json create mode 100644 libs/hash-graph-client/python/yarn.lock create mode 100644 libs/hash-graph-sdk/python/.gitattributes create mode 100644 libs/hash-graph-sdk/python/LICENSE.md create mode 100644 libs/hash-graph-sdk/python/README.md create mode 100644 libs/hash-graph-sdk/python/examples/query_company_entities.py create mode 100644 libs/hash-graph-sdk/python/examples/query_company_entities_limited_axes.py create mode 100644 libs/hash-graph-sdk/python/examples/query_company_entity_type.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/__init__.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/client/__init__.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/client/_compat.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/client/blocking.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/client/concurrent.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/filter/__init__.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/filter/base.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/filter/config.json create mode 100644 libs/hash-graph-sdk/python/graph_sdk/filter/path.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/options.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/py.typed create mode 100644 libs/hash-graph-sdk/python/graph_sdk/query.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/types.py create mode 100644 libs/hash-graph-sdk/python/graph_sdk/utils.py create mode 100644 libs/hash-graph-sdk/python/package.json create mode 100644 libs/hash-graph-sdk/python/poetry.lock create mode 100644 libs/hash-graph-sdk/python/poetry.toml create mode 100644 libs/hash-graph-sdk/python/pyproject.toml create mode 100644 libs/hash-graph-sdk/python/scripts/generate_blocking.py create mode 100644 libs/hash-graph-sdk/python/scripts/generate_filter.py create mode 100644 libs/hash-graph-sdk/python/turbo.json create mode 100644 libs/hash-graph-types/python/LICENSE.md create mode 100644 libs/hash-graph-types/python/README.md create mode 100644 libs/hash-graph-types/python/graph_types/__init__.py create mode 100644 libs/hash-graph-types/python/graph_types/_annotations/__init__.py create mode 100644 libs/hash-graph-types/python/graph_types/_annotations/const.py create mode 100644 libs/hash-graph-types/python/graph_types/_annotations/require.py create mode 100644 libs/hash-graph-types/python/graph_types/_schema.py create mode 100644 libs/hash-graph-types/python/graph_types/base.py create mode 100644 libs/hash-graph-types/python/graph_types/data_type.py create mode 100644 libs/hash-graph-types/python/graph_types/entity_type.py create mode 100644 libs/hash-graph-types/python/graph_types/property_type.py create mode 100644 libs/hash-graph-types/python/graph_types/py.typed create mode 100644 libs/hash-graph-types/python/package.json create mode 100644 libs/hash-graph-types/python/poetry.lock create mode 100644 libs/hash-graph-types/python/poetry.toml create mode 100644 libs/hash-graph-types/python/pyproject.toml create mode 100644 libs/hash-graph-types/python/turbo.json diff --git a/libs/hash-graph-client/python/.gitattributes b/libs/hash-graph-client/python/.gitattributes new file mode 100644 index 0000000..d3f0aed --- /dev/null +++ b/libs/hash-graph-client/python/.gitattributes @@ -0,0 +1 @@ +graph_client/models.py linguist-generated=true diff --git a/libs/hash-graph-client/python/.gitignore b/libs/hash-graph-client/python/.gitignore new file mode 100644 index 0000000..3a2a622 --- /dev/null +++ b/libs/hash-graph-client/python/.gitignore @@ -0,0 +1 @@ +scripts/openapi.bundle.json diff --git a/libs/hash-graph-client/python/LICENSE.md b/libs/hash-graph-client/python/LICENSE.md new file mode 100644 index 0000000..9a70d79 --- /dev/null +++ b/libs/hash-graph-client/python/LICENSE.md @@ -0,0 +1,606 @@ +# GNU Affero General Public License + +_Version 3, 19 November 2007_ +_Copyright © 2007 Free Software Foundation, Inc. <>_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +## Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: **(1)** assert copyright on the software, and **(2)** offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions + +“This License” refers to version 3 of the GNU Affero General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based +on the Program. + +To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that **(1)** displays an appropriate copyright notice, and **(2)** +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code + +The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work. + +A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other +than the work as a whole, that **(a)** is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and **(b)** serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +### 2. Basic Permissions + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +### 4. Conveying Verbatim Copies + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +- **a)** The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- **b)** The work must carry prominent notices stating that it is + released under this License and any conditions added under section 7. + This requirement modifies the requirement in section 4 to + “keep intact all notices”. +- **c)** You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- **d)** If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +- **a)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- **b)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either **(1)** a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or **(2)** access to copy the + Corresponding Source from a network server at no charge. +- **c)** Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- **d)** Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- **e)** Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A “User Product” is either **(1)** a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or **(2)** anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms + +“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +- **a)** Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- **b)** Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- **c)** Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- **d)** Limiting the use for publicity purposes of names of licensors or + authors of the material; or +- **e)** Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- **f)** Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + +All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +### 8. Termination + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated **(a)** +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and **(b)** permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents + +A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either **(1)** cause the Corresponding Source to be so +available, or **(2)** arrange to deprive yourself of the benefit of the +patent license for this particular work, or **(3)** arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license **(a)** in connection with copies of the covered work +conveyed by you (or copies made from those copies), or **(b)** primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16 + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. diff --git a/libs/hash-graph-client/python/README.md b/libs/hash-graph-client/python/README.md new file mode 100644 index 0000000..fcb98a3 --- /dev/null +++ b/libs/hash-graph-client/python/README.md @@ -0,0 +1,6 @@ +# HASH Graph client + +OpenAPI automatically generated client for HASH Graph. + +Due to current limitations in the auto-generation process, only the models are automatically generated. +The client code is manually written. diff --git a/libs/hash-graph-client/python/graph_client/__init__.py b/libs/hash-graph-client/python/graph_client/__init__.py new file mode 100644 index 0000000..30c9dd6 --- /dev/null +++ b/libs/hash-graph-client/python/graph_client/__init__.py @@ -0,0 +1,357 @@ +"""Client for the HASH API.""" + +from typing import Literal, TypeAlias, TypeVar +from uuid import UUID + +import httpx +from pydantic import BaseModel +from yarl import URL + +from graph_client.models import ( + CreateDataTypeRequest, + CreateEntityRequest, + CreateEntityTypeRequest, + CreatePropertyTypeRequest, + DataTypeQueryToken, + DataTypeStructuralQuery, + EntityMetadata, + EntityQueryToken, + EntityStructuralQuery, + EntityTypeQueryToken, + EntityTypeStructuralQuery, + LoadExternalDataTypeRequest, + LoadExternalEntityTypeRequest, + LoadExternalPropertyTypeRequest, + MaybeListOfOntologyElementMetadata, + OntologyElementMetadata, + PropertyTypeQueryToken, + PropertyTypeStructuralQuery, + Selector, + Subgraph, + UpdateDataTypeRequest, + UpdateEntityRequest, + UpdateEntityTypeRequest, + UpdatePropertyTypeRequest, +) + +T = TypeVar("T", bound=BaseModel) + +QueryToken: TypeAlias = ( + DataTypeQueryToken + | PropertyTypeQueryToken + | EntityTypeQueryToken + | EntityQueryToken + | Selector + | str + | float +) + +__all__ = ["GraphClient", "QueryToken", "models"] + + +async def _send_request( + endpoint: URL, + method: Literal["POST", "PUT"], + body: BaseModel, + actor: UUID, + response_t: type[T], +) -> T: + """Send a request to the HASH API.""" + async with httpx.AsyncClient() as client: + response = await client.request( + method, + str(endpoint), + json=body.model_dump(by_alias=True, mode="json"), + headers={ + "X-Authenticated-User-Actor-Id": str(actor), + }, + ) + + response.raise_for_status() + + json = response.json() + return response_t.model_validate(json, strict=False) + + +U = TypeVar("U") + + +def _assert_not_none(value: U | None) -> U: + """Assert that the value is not None.""" + if value is None: + msg = "value cannot be None" + raise ValueError(msg) + + return value + + +class GraphClient: + """Low-level implementation of the client for the HASH API.""" + + base: URL + actor: UUID | None + + def __init__(self, base: URL, *, actor: UUID | None = None) -> None: + """Initialize the client with the base URL.""" + self.base = base + self.actor = actor + + def _actor(self, override: UUID | None = None) -> UUID: + """Get the actor for the client.""" + actor = override or self.actor + return _assert_not_none(actor) + + async def query_entity_types( + self, + query: EntityTypeStructuralQuery, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query the HASH API for entity types.""" + endpoint = self.base / "entity-types" / "query" + + return await _send_request( + endpoint, + "POST", + query, + self._actor(actor), + Subgraph, + ) + + async def load_external_entity_type( + self, + request: LoadExternalEntityTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external entity type.""" + endpoint = self.base / "entity-types" / "load" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def create_entity_types( + self, + request: CreateEntityTypeRequest, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create an entity type.""" + endpoint = self.base / "entity-types" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + MaybeListOfOntologyElementMetadata, + ) + + async def update_entity_type( + self, + request: UpdateEntityTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update an entity type.""" + endpoint = self.base / "entity-types" + + return await _send_request( + endpoint, + "PUT", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def query_property_types( + self, + query: PropertyTypeStructuralQuery, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query the HASH API for property types.""" + endpoint = self.base / "property-types" / "query" + + return await _send_request( + endpoint, + "POST", + query, + self._actor(actor), + Subgraph, + ) + + async def load_external_property_type( + self, + request: LoadExternalPropertyTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external property type.""" + endpoint = self.base / "property-types" / "load" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def create_property_types( + self, + request: CreatePropertyTypeRequest, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create a property type.""" + endpoint = self.base / "property-types" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + MaybeListOfOntologyElementMetadata, + ) + + async def update_property_type( + self, + request: UpdatePropertyTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update a property type.""" + endpoint = self.base / "property-types" + + return await _send_request( + endpoint, + "PUT", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def query_data_types( + self, + query: DataTypeStructuralQuery, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query the HASH API for data types.""" + endpoint = self.base / "data-types" / "query" + + return await _send_request( + endpoint, + "POST", + query, + self._actor(actor), + Subgraph, + ) + + async def load_external_data_type( + self, + request: LoadExternalDataTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external data type.""" + endpoint = self.base / "data-types" / "load" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def create_data_types( + self, + request: CreateDataTypeRequest, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create a data type.""" + endpoint = self.base / "data-types" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + MaybeListOfOntologyElementMetadata, + ) + + async def update_data_type( + self, + request: UpdateDataTypeRequest, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update a data type.""" + endpoint = self.base / "data-types" + + return await _send_request( + endpoint, + "PUT", + request, + self._actor(actor), + OntologyElementMetadata, + ) + + async def query_entities( + self, + query: EntityStructuralQuery, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query the HASH API for entities.""" + endpoint = self.base / "entities" / "query" + + return await _send_request( + endpoint, + "POST", + query, + self._actor(actor), + Subgraph, + ) + + async def create_entity( + self, + request: CreateEntityRequest, + *, + actor: UUID | None = None, + ) -> EntityMetadata: + """Create an entity.""" + endpoint = self.base / "entities" + + return await _send_request( + endpoint, + "POST", + request, + self._actor(actor), + EntityMetadata, + ) + + async def update_entity( + self, + request: UpdateEntityRequest, + *, + actor: UUID | None = None, + ) -> EntityMetadata: + """Update an entity.""" + endpoint = self.base / "entities" + + return await _send_request( + endpoint, + "PUT", + request, + self._actor(actor), + EntityMetadata, + ) diff --git a/libs/hash-graph-client/python/graph_client/models.py b/libs/hash-graph-client/python/graph_client/models.py new file mode 100644 index 0000000..81d638c --- /dev/null +++ b/libs/hash-graph-client/python/graph_client/models.py @@ -0,0 +1,1238 @@ +from __future__ import annotations +from graph_client.schema import OntologyTypeSchema +from datetime import datetime +from enum import Enum +from typing import Any, Literal +from uuid import UUID +from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel + +class AccountGroupId(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class AccountGroupPermission(Enum): + add_member = 'add_member' + remove_member = 'remove_member' + +class AccountId(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class DataTypeOwnerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class DataTypeOwnerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class DataTypeOwnerSubject(RootModel[DataTypeOwnerSubjectItem | DataTypeOwnerSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeOwnerSubjectItem | DataTypeOwnerSubjectItem1 = Field(..., discriminator='kind') + +class DataTypePermission(Enum): + update = 'update' + view = 'view' + +class DataTypeQueryToken(Enum): + """ + A single token in a [`DataTypeQueryPath`]. + """ + base_url = 'baseUrl' + version = 'version' + versioned_url = 'versionedUrl' + owned_by_id = 'ownedById' + record_created_by_id = 'recordCreatedById' + record_archived_by_id = 'recordArchivedById' + title = 'title' + description = 'description' + type = 'type' + +class DataTypeRelationAndSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['owner'] + subject: DataTypeOwnerSubject + +class DataTypeViewerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['public'] + +class DataTypeViewerSubject(RootModel[DataTypeViewerSubjectItem]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeViewerSubjectItem + +class DecisionTime(RootModel[Literal['decisionTime']]): + model_config = ConfigDict(populate_by_name=True) + root: Literal['decisionTime'] = Field(..., description='Time axis for the decision time.\n\nThis is used as the generic argument to time-related structs and can be used as tag value.') + +class EdgeResolveDepths(BaseModel): + model_config = ConfigDict(populate_by_name=True) + incoming: int = Field(..., ge=0) + outgoing: int = Field(..., ge=0) + +class EntityEditionId(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class EntityEditorSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class EntityEditorSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class EntityEditorSubject(RootModel[EntityEditorSubjectItem | EntityEditorSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: EntityEditorSubjectItem | EntityEditorSubjectItem1 = Field(..., discriminator='kind') + +class EntityId(RootModel[str]): + model_config = ConfigDict(populate_by_name=True) + root: str + +class EntityOwnerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class EntityOwnerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class EntityOwnerSubject(RootModel[EntityOwnerSubjectItem | EntityOwnerSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: EntityOwnerSubjectItem | EntityOwnerSubjectItem1 = Field(..., discriminator='kind') + +class EntityPermission(Enum): + update = 'update' + view = 'view' + +class EntityProperties(BaseModel): + """ + The properties of an entity. + + When expressed as JSON, this should validate against its respective entity type(s). + """ + model_config = ConfigDict(populate_by_name=True) + +class EntityQueryToken(Enum): + """ + A single token in an [`EntityQueryPath`]. + """ + uuid = 'uuid' + edition_id = 'editionId' + archived = 'archived' + draft = 'draft' + owned_by_id = 'ownedById' + record_created_by_id = 'recordCreatedById' + type = 'type' + properties = 'properties' + incoming_links = 'incomingLinks' + outgoing_links = 'outgoingLinks' + left_entity = 'leftEntity' + right_entity = 'rightEntity' + left_to_right_order = 'leftToRightOrder' + right_to_left_order = 'rightToLeftOrder' + +class EntityRecordId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + edition_id: EntityEditionId = Field(..., alias='editionId') + entity_id: EntityId = Field(..., alias='entityId') + +class EntityRelationAndSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['owner'] + subject: EntityOwnerSubject + +class EntityRelationAndSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['editor'] + subject: EntityEditorSubject + +class EntityTypeInstantiatorSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class EntityTypeInstantiatorSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class EntityTypeInstantiatorSubjectItem2(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['public'] + +class EntityTypeInstantiatorSubject(RootModel[EntityTypeInstantiatorSubjectItem | EntityTypeInstantiatorSubjectItem1 | EntityTypeInstantiatorSubjectItem2]): + model_config = ConfigDict(populate_by_name=True) + root: EntityTypeInstantiatorSubjectItem | EntityTypeInstantiatorSubjectItem1 | EntityTypeInstantiatorSubjectItem2 = Field(..., discriminator='kind') + +class EntityTypeOwnerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class EntityTypeOwnerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class EntityTypeOwnerSubject(RootModel[EntityTypeOwnerSubjectItem | EntityTypeOwnerSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: EntityTypeOwnerSubjectItem | EntityTypeOwnerSubjectItem1 = Field(..., discriminator='kind') + +class EntityTypePermission(Enum): + update = 'update' + view = 'view' + instantiate = 'instantiate' + +class EntityTypeQueryToken(Enum): + """ + A single token in a [`EntityTypeQueryPath`]. + """ + base_url = 'baseUrl' + version = 'version' + versioned_url = 'versionedUrl' + owned_by_id = 'ownedById' + record_created_by_id = 'recordCreatedById' + record_archived_by_id = 'recordArchivedById' + title = 'title' + description = 'description' + examples = 'examples' + properties = 'properties' + required = 'required' + label_property = 'labelProperty' + icon = 'icon' + links = 'links' + inherits_from = 'inheritsFrom' + children = 'children' + +class EntityTypeRelationAndSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['owner'] + subject: EntityTypeOwnerSubject + +class EntityTypeRelationAndSubjectItem2(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['instantiator'] + subject: EntityTypeInstantiatorSubject + +class EntityTypeViewerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['public'] + +class EntityTypeViewerSubject(RootModel[EntityTypeViewerSubjectItem]): + model_config = ConfigDict(populate_by_name=True) + root: EntityTypeViewerSubjectItem + +class EntityUuid(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class EntityViewerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['public'] + +class EntityViewerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class EntityViewerSubjectItem2(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class EntityViewerSubject(RootModel[EntityViewerSubjectItem | EntityViewerSubjectItem1 | EntityViewerSubjectItem2]): + model_config = ConfigDict(populate_by_name=True) + root: EntityViewerSubjectItem | EntityViewerSubjectItem1 | EntityViewerSubjectItem2 = Field(..., discriminator='kind') + +class ParameterExpression(BaseModel): + model_config = ConfigDict(populate_by_name=True) + parameter: Any + +class KnowledgeGraphEdgeKind(Enum): + has_left_entity = 'HAS_LEFT_ENTITY' + has_right_entity = 'HAS_RIGHT_ENTITY' + +class LinkOrder(RootModel[int]): + model_config = ConfigDict(populate_by_name=True) + root: int + +class ModifyRelationshipOperation(Enum): + """ + Used for mutating a single relationship within the service. + """ + touch = 'touch' + create = 'create' + delete = 'delete' + +class NullableTimestamp(RootModel[datetime | None]): + model_config = ConfigDict(populate_by_name=True) + root: datetime | None = None + +class OntologyEdgeKind(Enum): + inherits_from = 'INHERITS_FROM' + constrains_values_on = 'CONSTRAINS_VALUES_ON' + constrains_properties_on = 'CONSTRAINS_PROPERTIES_ON' + constrains_links_on = 'CONSTRAINS_LINKS_ON' + constrains_link_destinations_on = 'CONSTRAINS_LINK_DESTINATIONS_ON' + +class OntologyTypeRecordId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + base_url: str = Field(..., alias='baseUrl') + version: int = Field(..., ge=0) + +class OntologyTypeVersion(RootModel[int]): + model_config = ConfigDict(populate_by_name=True) + root: int = Field(..., ge=0) + +class UnboundedBound(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['unbounded'] + +class OutgoingEdgeResolveDepth(BaseModel): + model_config = ConfigDict(populate_by_name=True) + outgoing: int = Field(..., ge=0) + +class OwnedById(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class PermissionResponse(BaseModel): + model_config = ConfigDict(populate_by_name=True) + has_permission: bool + +class PropertyTypeOwnerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class PropertyTypeOwnerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class PropertyTypeOwnerSubject(RootModel[PropertyTypeOwnerSubjectItem | PropertyTypeOwnerSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: PropertyTypeOwnerSubjectItem | PropertyTypeOwnerSubjectItem1 = Field(..., discriminator='kind') + +class PropertyTypePermission(Enum): + update = 'update' + view = 'view' + +class PropertyTypeQueryToken(Enum): + """ + A single token in a [`DataTypeQueryPath`]. + """ + base_url = 'baseUrl' + version = 'version' + versioned_url = 'versionedUrl' + owned_by_id = 'ownedById' + record_created_by_id = 'recordCreatedById' + record_archived_by_id = 'recordArchivedById' + title = 'title' + description = 'description' + data_types = 'dataTypes' + property_types = 'propertyTypes' + +class PropertyTypeRelationAndSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['owner'] + subject: PropertyTypeOwnerSubject + +class PropertyTypeViewerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['public'] + +class PropertyTypeViewerSubject(RootModel[PropertyTypeViewerSubjectItem]): + model_config = ConfigDict(populate_by_name=True) + root: PropertyTypeViewerSubjectItem + +class PinnedDecisionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: DecisionTime + timestamp: datetime + +class UnresolvedPinnedDecisionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: DecisionTime + timestamp: NullableTimestamp + +class RecordArchivedById(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class RecordCreatedById(RootModel[UUID]): + model_config = ConfigDict(populate_by_name=True) + root: UUID + +class Selector(RootModel[Literal['*']]): + model_config = ConfigDict(populate_by_name=True) + root: Literal['*'] + +class SharedEdgeKind(RootModel[Literal['IS_OF_TYPE']]): + model_config = ConfigDict(populate_by_name=True) + root: Literal['IS_OF_TYPE'] + +class Timestamp(RootModel[datetime]): + model_config = ConfigDict(populate_by_name=True) + root: datetime + +class TransactionTime(RootModel[Literal['transactionTime']]): + model_config = ConfigDict(populate_by_name=True) + root: Literal['transactionTime'] = Field(..., description='Time axis for the transaction time.\n\nThis is used as the generic argument to time-related structs and can be used as tag value.') + +class ValidationOperation(RootModel[Literal['all']]): + model_config = ConfigDict(populate_by_name=True) + root: Literal['all'] + +class WebOwnerSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['account'] + subject_id: AccountId = Field(..., alias='subjectId') + +class WebOwnerSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['accountGroup'] + subject_id: AccountGroupId = Field(..., alias='subjectId') + +class WebOwnerSubject(RootModel[WebOwnerSubjectItem | WebOwnerSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: WebOwnerSubjectItem | WebOwnerSubjectItem1 = Field(..., discriminator='kind') + +class WebPermission(Enum): + update = 'update' + create_entity = 'create_entity' + create_entity_type = 'create_entity_type' + create_property_type = 'create_property_type' + create_data_type = 'create_data_type' + +class WebRelationAndSubjectItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['owner'] + subject: WebOwnerSubject + +class WebRelationAndSubject(RootModel[WebRelationAndSubjectItem]): + model_config = ConfigDict(populate_by_name=True) + root: WebRelationAndSubjectItem = Field(..., discriminator='relation') + +class UpdateDataType(BaseModel): + """ + The contents of a Data Type update request + """ + model_config = ConfigDict(extra='allow', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/data-type'] = Field(..., alias='$schema') + kind: Literal['dataType'] + title: str + description: str | None = None + type: str + +class VersionedURL(RootModel[AnyUrl]): + model_config = ConfigDict(populate_by_name=True) + root: AnyUrl = Field(..., description='The versioned URL of a Block Protocol ontology type (the $id of the schema). It should be of the form `${baseUrl}v/${versionNumber}`', max_length=2048, title='Versioned URL') + +class DataType(OntologyTypeSchema): + """ + Specifies the structure of a Data Type + """ + model_config = ConfigDict(extra='allow', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/data-type'] = Field(..., alias='$schema') + kind: Literal['dataType'] + identifier: VersionedURL = Field(..., alias='$id') + title: str + description: str | None = None + type: str + +class BaseURL(RootModel[AnyUrl]): + model_config = ConfigDict(populate_by_name=True) + root: AnyUrl = Field(..., description='The base URL of a Block Protocol ontology type (the $id of the schema, without the versioned suffix). It should a valid URL, with a trailing slash.', max_length=2048, title='Base URL') + +class DataTypeReference(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + field_ref: VersionedURL = Field(..., alias='$ref') + +class EntityTypeReference(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + field_ref: VersionedURL = Field(..., alias='$ref') + +class Items1(BaseModel): + """ + Specifies a set of entity types inside a oneOf + """ + model_config = ConfigDict(extra='forbid', populate_by_name=True) + one_of: list[EntityTypeReference] | None = Field(None, alias='oneOf') + +class LinkTypeObject(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + type: Literal['array'] + ordered: bool + items: Items1 = Field(..., description='Specifies a set of entity types inside a oneOf') + min_items: int | None = Field(None, alias='minItems', ge=0) + max_items: int | None = Field(None, alias='maxItems', ge=0) + +class LinkTypeObject1(RootModel[dict[str, LinkTypeObject]]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, LinkTypeObject] + +class StatusCode(Enum): + """ + The canonical status codes for software within the HASH ecosystem. + Sometimes multiple status codes may apply. Services should return the most specific status code + that applies. For example, prefer `OutOfRange` over `FailedPrecondition` if both codes + apply. Similarly prefer `NotFound` or `AlreadyExists` over `FailedPrecondition`. + """ + aborted = 'ABORTED' + already_exists = 'ALREADY_EXISTS' + cancelled = 'CANCELLED' + data_loss = 'DATA_LOSS' + deadline_exceeded = 'DEADLINE_EXCEEDED' + failed_precondition = 'FAILED_PRECONDITION' + internal = 'INTERNAL' + invalid_argument = 'INVALID_ARGUMENT' + not_found = 'NOT_FOUND' + ok = 'OK' + out_of_range = 'OUT_OF_RANGE' + permission_denied = 'PERMISSION_DENIED' + resource_exhausted = 'RESOURCE_EXHAUSTED' + unauthenticated = 'UNAUTHENTICATED' + unavailable = 'UNAVAILABLE' + unimplemented = 'UNIMPLEMENTED' + unknown = 'UNKNOWN' + +class RecordStringAny(BaseModel): + """ + Construct a type with a set of properties K of type T + """ + model_config = ConfigDict(populate_by_name=True) + +class ErrorInfo(BaseModel): + model_config = ConfigDict(populate_by_name=True) + reason: str = Field(..., description='The reason of the error. This is a constant value that identifies the proximate cause of\nthe error. Error reasons are unique within a particular domain of errors. This should be at\nmost 63 characters and match a regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, which\nrepresents UPPER_SNAKE_CASE.', title='reason') + domain: str = Field(..., description='The logical grouping to which the "reason" belongs.\nThe error domain is typically the registered service name of the tool or product that\ngenerates the error.', title='domain') + metadata: RecordStringAny = Field(..., description='Additional structured details about this error.\n\nKeys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in length. When\nidentifying the current value of an exceeded limit, the units should be contained in the\nkey, not the value. For example, rather than {"instanceLimit": "100/request"}, should be\nreturned as, {"instanceLimitPerRequest": "100"}, if the client exceeds the number of\ninstances that can be created in a single (batch) request.', title='metadata') + +class RequestInfo(BaseModel): + model_config = ConfigDict(populate_by_name=True) + request_id: str = Field(..., alias='requestId', description="An opaque string that should only be interpreted by the service generating it. For example, it\ncan be used to identify requests in the service's logs.", title='requestId') + serving_data: str = Field(..., alias='servingData', description='Any data that was used to serve this request. For example, an encrypted stack trace that can be\nsent back to the service provider for debugging.', title='servingData') + +class ResourceInfo(BaseModel): + model_config = ConfigDict(populate_by_name=True) + resource_type: str = Field(..., alias='resourceType', description='A name for the type of resource being accessed.\n\nFor example "SQL table", "Entity", "Property Type", "Redis"; or the type URL of the resource:\ne.g. "https://blockprotocol.org/type-system/0.3/schema/meta/entity-type".', title='resourceType') + resource_name: str = Field(..., alias='resourceName', description='The name of the resource being accessed.\n\nFor example, an ontology type ID: `https://hash.ai/@alice/types/entity-type/Person/`, if the current\nerror is [@local/status/StatusCode.PermissionDenied].', title='resourceName') + owner: str | None = Field(None, description="The owner of the resource (optional).\n\nFor example, a User's entity ID: `2cfa262a-f49a-4a61-a9c5-80a0c5959994%45e528cb-801d-49d1-8f71-d9e2af38a5e7`;", title='owner') + description: str = Field(..., description="Describes what error is encountered when accessing this resource.\n\nFor example, updating a property on a user's entity may require write permission on that property.", title='description') + +class Status(BaseModel): + model_config = ConfigDict(populate_by_name=True) + code: StatusCode = Field(..., title='code') + message: str | None = Field(None, description='A developer-facing description of the status.\n\nWhere possible, this should provide guiding advice for debugging and/or handling the error.') + contents: list[ErrorInfo | RequestInfo | ResourceInfo] + +class PropertyObjectReference(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + field_ref: BaseURL = Field(..., alias='$ref') + +class ArchiveDataTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_archive: VersionedURL = Field(..., alias='typeToArchive') + +class ArchiveEntityTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_archive: VersionedURL = Field(..., alias='typeToArchive') + +class ArchivePropertyTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_archive: VersionedURL = Field(..., alias='typeToArchive') + +class InclusiveBound(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['inclusive'] + limit: Timestamp + +class ClosedTemporalBound(RootModel[InclusiveBound]): + model_config = ConfigDict(populate_by_name=True) + root: InclusiveBound = Field(..., discriminator='kind') + +class CreateDataTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + owned_by_id: OwnedById = Field(..., alias='ownedById') + schema_: DataType | list[DataType] = Field(..., alias='schema') + +class CreateWebRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + owned_by_id: OwnedById = Field(..., alias='ownedById') + owner: WebOwnerSubject + +class DataTypeRelationAndSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['viewer'] + subject: DataTypeViewerSubject + +class DataTypeRelationAndSubject(RootModel[DataTypeRelationAndSubjectItem | DataTypeRelationAndSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeRelationAndSubjectItem | DataTypeRelationAndSubjectItem1 = Field(..., discriminator='relation') + +class DataTypeVertexId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + base_id: BaseURL = Field(..., alias='baseId') + revision_id: OntologyTypeVersion = Field(..., alias='revisionId') + +class EntityLinkOrder(BaseModel): + model_config = ConfigDict(populate_by_name=True) + left_to_right_order: LinkOrder | None = Field(None, alias='leftToRightOrder') + right_to_left_order: LinkOrder | None = Field(None, alias='rightToLeftOrder') + +class EntityRelationAndSubjectItem2(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['viewer'] + subject: EntityViewerSubject + +class EntityRelationAndSubject(RootModel[EntityRelationAndSubjectItem | EntityRelationAndSubjectItem1 | EntityRelationAndSubjectItem2]): + model_config = ConfigDict(populate_by_name=True) + root: EntityRelationAndSubjectItem | EntityRelationAndSubjectItem1 | EntityRelationAndSubjectItem2 = Field(..., discriminator='relation') + +class EntityTypeRelationAndSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['viewer'] + subject: EntityTypeViewerSubject + +class EntityTypeRelationAndSubject(RootModel[EntityTypeRelationAndSubjectItem | EntityTypeRelationAndSubjectItem1 | EntityTypeRelationAndSubjectItem2]): + model_config = ConfigDict(populate_by_name=True) + root: EntityTypeRelationAndSubjectItem | EntityTypeRelationAndSubjectItem1 | EntityTypeRelationAndSubjectItem2 = Field(..., discriminator='relation') + +class EntityTypeVertexId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + base_id: BaseURL = Field(..., alias='baseId') + revision_id: OntologyTypeVersion = Field(..., alias='revisionId') + +class EntityVertexId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + base_id: EntityId = Field(..., alias='baseId') + revision_id: Timestamp = Field(..., alias='revisionId') + +class PathExpression(BaseModel): + model_config = ConfigDict(populate_by_name=True) + path: list[DataTypeQueryToken | PropertyTypeQueryToken | EntityTypeQueryToken | EntityQueryToken | Selector | str | float] + +class FilterExpression(RootModel[PathExpression | ParameterExpression]): + model_config = ConfigDict(populate_by_name=True) + root: PathExpression | ParameterExpression + +class GraphResolveDepths(BaseModel): + """ + TODO: DOC - + """ + model_config = ConfigDict(populate_by_name=True) + constrains_link_destinations_on: OutgoingEdgeResolveDepth = Field(..., alias='constrainsLinkDestinationsOn') + constrains_links_on: OutgoingEdgeResolveDepth = Field(..., alias='constrainsLinksOn') + constrains_properties_on: OutgoingEdgeResolveDepth = Field(..., alias='constrainsPropertiesOn') + constrains_values_on: OutgoingEdgeResolveDepth = Field(..., alias='constrainsValuesOn') + has_left_entity: EdgeResolveDepths = Field(..., alias='hasLeftEntity') + has_right_entity: EdgeResolveDepths = Field(..., alias='hasRightEntity') + inherits_from: OutgoingEdgeResolveDepth = Field(..., alias='inheritsFrom') + is_of_type: OutgoingEdgeResolveDepth = Field(..., alias='isOfType') + +class ExclusiveBound(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: Literal['exclusive'] + limit: Timestamp + +class LimitedTemporalBound(RootModel[InclusiveBound | ExclusiveBound]): + model_config = ConfigDict(populate_by_name=True) + root: InclusiveBound | ExclusiveBound = Field(..., discriminator='kind') + +class LinkData(EntityLinkOrder): + """ + The associated information for 'Link' entities + """ + model_config = ConfigDict(populate_by_name=True) + left_entity_id: EntityId = Field(..., alias='leftEntityId') + right_entity_id: EntityId = Field(..., alias='rightEntityId') + +class LoadExternalDataTypeRequestItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + data_type_id: VersionedURL = Field(..., alias='dataTypeId') + +class LoadExternalDataTypeRequestItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + schema_: DataType = Field(..., alias='schema') + +class LoadExternalDataTypeRequest(RootModel[LoadExternalDataTypeRequestItem | LoadExternalDataTypeRequestItem1]): + model_config = ConfigDict(populate_by_name=True) + root: LoadExternalDataTypeRequestItem | LoadExternalDataTypeRequestItem1 + +class LoadExternalEntityTypeRequestItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + entity_type_id: VersionedURL = Field(..., alias='entityTypeId') + +class LoadExternalPropertyTypeRequestItem(BaseModel): + model_config = ConfigDict(populate_by_name=True) + property_type_id: VersionedURL = Field(..., alias='propertyTypeId') + +class ModifyDataTypeAuthorizationRelationship(BaseModel): + model_config = ConfigDict(populate_by_name=True) + operation: ModifyRelationshipOperation + relation_and_subject: DataTypeRelationAndSubject = Field(..., alias='relationAndSubject') + resource: VersionedURL + +class ModifyEntityAuthorizationRelationship(BaseModel): + model_config = ConfigDict(populate_by_name=True) + operation: ModifyRelationshipOperation + relation_subject: EntityRelationAndSubject = Field(..., alias='relationSubject') + resource: EntityId + +class ModifyEntityTypeAuthorizationRelationship(BaseModel): + model_config = ConfigDict(populate_by_name=True) + operation: ModifyRelationshipOperation + relation_and_subject: EntityTypeRelationAndSubject = Field(..., alias='relationAndSubject') + resource: VersionedURL + +class ModifyWebAuthorizationRelationship(BaseModel): + model_config = ConfigDict(populate_by_name=True) + operation: ModifyRelationshipOperation + relation_and_subject: WebRelationAndSubject = Field(..., alias='relationAndSubject') + resource: OwnedById + +class OpenTemporalBound(RootModel[ExclusiveBound | UnboundedBound]): + model_config = ConfigDict(populate_by_name=True) + root: ExclusiveBound | UnboundedBound = Field(..., discriminator='kind') + +class PropertyTypeRelationAndSubjectItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + relation: Literal['viewer'] + subject: PropertyTypeViewerSubject + +class PropertyTypeRelationAndSubject(RootModel[PropertyTypeRelationAndSubjectItem | PropertyTypeRelationAndSubjectItem1]): + model_config = ConfigDict(populate_by_name=True) + root: PropertyTypeRelationAndSubjectItem | PropertyTypeRelationAndSubjectItem1 = Field(..., discriminator='relation') + +class PropertyTypeVertexId(BaseModel): + model_config = ConfigDict(populate_by_name=True) + base_id: BaseURL = Field(..., alias='baseId') + revision_id: OntologyTypeVersion = Field(..., alias='revisionId') + +class ProvenanceMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + record_archived_by_id: RecordArchivedById | None = Field(None, alias='recordArchivedById') + record_created_by_id: RecordCreatedById = Field(..., alias='recordCreatedById') + +class PinnedTransactionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: TransactionTime + timestamp: datetime + +class UnresolvedPinnedTransactionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: TransactionTime + timestamp: NullableTimestamp + +class TemporalBound(RootModel[UnboundedBound | InclusiveBound | ExclusiveBound]): + model_config = ConfigDict(populate_by_name=True) + root: UnboundedBound | InclusiveBound | ExclusiveBound = Field(..., discriminator='kind') + +class UnarchiveDataTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_unarchive: VersionedURL = Field(..., alias='typeToUnarchive') + +class UnarchiveEntityTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_unarchive: VersionedURL = Field(..., alias='typeToUnarchive') + +class UnarchivePropertyTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + type_to_unarchive: VersionedURL = Field(..., alias='typeToUnarchive') + +class UnresolvedRightBoundedTemporalInterval(BaseModel): + model_config = ConfigDict(populate_by_name=True) + end: LimitedTemporalBound | None = Field(...) + start: TemporalBound | None = Field(...) + +class UpdateDataTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + schema_: UpdateDataType = Field(..., alias='schema') + type_to_update: VersionedURL = Field(..., alias='typeToUpdate') + +class UpdateEntityRequest(EntityLinkOrder): + model_config = ConfigDict(populate_by_name=True) + archived: bool + draft: bool + entity_id: EntityId = Field(..., alias='entityId') + entity_type_id: VersionedURL = Field(..., alias='entityTypeId') + properties: EntityProperties + +class ValidateEntityRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + entity_type_id: VersionedURL = Field(..., alias='entityTypeId') + link_data: LinkData | None = Field(None, alias='linkData') + operations: list[ValidationOperation] + properties: EntityProperties + +class PropertyTypeObjectItem(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + type: Literal['array'] + items: PropertyObjectReference + min_items: int | None = Field(None, alias='minItems', ge=0) + max_items: int | None = Field(None, alias='maxItems', ge=0) + +class PropertyTypeObject(RootModel[dict[str, PropertyObjectReference | PropertyTypeObjectItem]]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, PropertyObjectReference | PropertyTypeObjectItem] = Field(..., description='A JSON object where each entry is constrained by a property type.', title='Property Type Object') + +class PropertyObjectValue(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + type: Literal['object'] + properties: PropertyTypeObject + +class EntityType(OntologyTypeSchema): + """ + Specifies the structure of a Block Protocol entity type + """ + model_config = ConfigDict(extra='forbid', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/entity-type'] = Field(..., alias='$schema') + kind: Literal['entityType'] + identifier: VersionedURL = Field(..., alias='$id') + type: Literal['object'] + title: str + description: str | None = None + all_of: list[EntityTypeReference] | None = Field(None, alias='allOf') + examples: list[dict[str, Any]] | None = None + properties: PropertyTypeObject + required: list[BaseURL] | None = None + links: LinkTypeObject1 | None = None + +class UpdateEntityType(BaseModel): + """ + The contents of an Entity Type update request + """ + model_config = ConfigDict(extra='forbid', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/entity-type'] = Field(..., alias='$schema') + kind: Literal['entityType'] + type: Literal['object'] + title: str + description: str | None = None + examples: list[dict[str, Any]] | None = None + properties: PropertyTypeObject + required: list[BaseURL] | None = None + links: LinkTypeObject1 | None = None + +class CreateEntityRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + draft: bool + entity_type_id: VersionedURL = Field(..., alias='entityTypeId') + entity_uuid: EntityUuid | None = Field(None, alias='entityUuid') + link_data: LinkData | None = Field(None, alias='linkData') + owned_by_id: OwnedById = Field(..., alias='ownedById') + owner: OwnedById + properties: EntityProperties + +class CreateEntityTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + icon: str | None = None + label_property: BaseURL | None = Field(None, alias='labelProperty') + owned_by_id: OwnedById = Field(..., alias='ownedById') + schema_: EntityType | list[EntityType] = Field(..., alias='schema') + +class EqualFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + equal: list[FilterExpression] = Field(..., max_length=2, min_length=2) + +class NotEqualFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + not_equal: list[FilterExpression] = Field(..., alias='notEqual', max_length=2, min_length=2) + +class StartsWithFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + starts_with: list[FilterExpression] = Field(..., alias='startsWith', max_length=2, min_length=2) + +class EndsWithFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ends_with: list[FilterExpression] = Field(..., alias='endsWith', max_length=2, min_length=2) + +class ContainsSegmentFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + contains_segment: list[FilterExpression] = Field(..., alias='containsSegment', max_length=2, min_length=2) + +class GraphElementVertexId(RootModel[DataTypeVertexId | PropertyTypeVertexId | EntityTypeVertexId | EntityVertexId]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeVertexId | PropertyTypeVertexId | EntityTypeVertexId | EntityVertexId + +class LeftClosedTemporalInterval(BaseModel): + model_config = ConfigDict(populate_by_name=True) + end: OpenTemporalBound + start: ClosedTemporalBound + +class LoadExternalEntityTypeRequestItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + icon: str | None = None + label_property: BaseURL | None = None + schema_: EntityType = Field(..., alias='schema') + +class LoadExternalEntityTypeRequest(RootModel[LoadExternalEntityTypeRequestItem | LoadExternalEntityTypeRequestItem1]): + model_config = ConfigDict(populate_by_name=True) + root: LoadExternalEntityTypeRequestItem | LoadExternalEntityTypeRequestItem1 + +class ModifyPropertyTypeAuthorizationRelationship(BaseModel): + model_config = ConfigDict(populate_by_name=True) + operation: ModifyRelationshipOperation + relation_and_subject: PropertyTypeRelationAndSubject = Field(..., alias='relationAndSubject') + resource: VersionedURL + +class OntologyTemporalMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + transaction_time: LeftClosedTemporalInterval = Field(..., alias='transactionTime') + +class OntologyTypeVertexId(RootModel[DataTypeVertexId | PropertyTypeVertexId | EntityTypeVertexId]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeVertexId | PropertyTypeVertexId | EntityTypeVertexId + +class UnresolvedVariableDecisionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: DecisionTime + interval: UnresolvedRightBoundedTemporalInterval + +class QueryTemporalAxesUnresolvedDecisionTime(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pinned: UnresolvedPinnedTransactionAxis = Field(..., title='UnresolvedPinnedTransactionAxis') + variable: UnresolvedVariableDecisionAxis = Field(..., title='UnresolvedVariableDecisionAxis') + +class UnresolvedVariableTransactionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: TransactionTime + interval: UnresolvedRightBoundedTemporalInterval + +class QueryTemporalAxesUnresolvedTransactionTime(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pinned: UnresolvedPinnedDecisionAxis = Field(..., title='UnresolvedPinnedDecisionAxis') + variable: UnresolvedVariableTransactionAxis = Field(..., title='UnresolvedVariableTransactionAxis') + +class QueryTemporalAxesUnresolved(RootModel[QueryTemporalAxesUnresolvedDecisionTime | QueryTemporalAxesUnresolvedTransactionTime]): + model_config = ConfigDict(populate_by_name=True) + root: QueryTemporalAxesUnresolvedDecisionTime | QueryTemporalAxesUnresolvedTransactionTime = Field(..., description='Defines the two possible combinations of pinned/variable temporal axes that are used in queries\nthat return [`Subgraph`]s.\n\nThe [`VariableTemporalAxisUnresolved`] is optionally bounded, in the absence of provided\nbounds an inclusive bound at the timestamp at point of resolving is assumed.\n\n[`Subgraph`]: crate::subgraph::Subgraph') + +class RightBoundedTemporalInterval(BaseModel): + model_config = ConfigDict(populate_by_name=True) + end: LimitedTemporalBound + start: TemporalBound + +class UpdateEntityTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + icon: str | None = None + label_property: BaseURL | None = Field(None, alias='labelProperty') + schema_: UpdateEntityType = Field(..., alias='schema') + type_to_update: VersionedURL = Field(..., alias='typeToUpdate') + +class CustomOwnedOntologyElementMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + owned_by_id: OwnedById = Field(..., alias='ownedById') + provenance: ProvenanceMetadata + temporal_versioning: OntologyTemporalMetadata = Field(..., alias='temporalVersioning') + +class CustomExternalOntologyElementMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + fetched_at: str = Field(..., alias='fetchedAt') + provenance: ProvenanceMetadata + temporal_versioning: OntologyTemporalMetadata = Field(..., alias='temporalVersioning') + +class CustomOntologyMetadata(RootModel[CustomOwnedOntologyElementMetadata | CustomExternalOntologyElementMetadata]): + model_config = ConfigDict(populate_by_name=True) + root: CustomOwnedOntologyElementMetadata | CustomExternalOntologyElementMetadata + +class EntityIdWithInterval(BaseModel): + model_config = ConfigDict(populate_by_name=True) + entity_id: EntityId = Field(..., alias='entityId') + interval: LeftClosedTemporalInterval + +class EntityTemporalMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + decision_time: LeftClosedTemporalInterval = Field(..., alias='decisionTime') + transaction_time: LeftClosedTemporalInterval = Field(..., alias='transactionTime') + +class EntityTypeMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + custom: CustomOntologyMetadata + icon: str | None = None + label_property: BaseURL | None = Field(None, alias='labelProperty') + record_id: OntologyTypeRecordId = Field(..., alias='recordId') + +class EntityTypeWithMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + metadata: EntityTypeMetadata + schema_: EntityType = Field(..., alias='schema') + +class KnowledgeGraphToKnowledgeGraphOutwardEdge(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: KnowledgeGraphEdgeKind + reversed: bool + right_endpoint: EntityIdWithInterval = Field(..., alias='rightEndpoint') + +class KnowledgeGraphToOntologyOutwardEdge(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: SharedEdgeKind + reversed: bool + right_endpoint: OntologyTypeVertexId = Field(..., alias='rightEndpoint') + +class KnowledgeGraphOutwardEdge(RootModel[KnowledgeGraphToKnowledgeGraphOutwardEdge | KnowledgeGraphToOntologyOutwardEdge]): + model_config = ConfigDict(populate_by_name=True) + root: KnowledgeGraphToKnowledgeGraphOutwardEdge | KnowledgeGraphToOntologyOutwardEdge + +class MaybeListOfEntityTypeMetadata(RootModel[EntityTypeMetadata | list[EntityTypeMetadata]]): + model_config = ConfigDict(populate_by_name=True) + root: EntityTypeMetadata | list[EntityTypeMetadata] + +class OntologyElementMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + custom: CustomOntologyMetadata + record_id: OntologyTypeRecordId = Field(..., alias='recordId') + +class OntologyToOntologyOutwardEdge(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: OntologyEdgeKind + reversed: bool + right_endpoint: OntologyTypeVertexId = Field(..., alias='rightEndpoint') + +class OntologyToKnowledgeGraphOutwardEdge(BaseModel): + model_config = ConfigDict(populate_by_name=True) + kind: SharedEdgeKind + reversed: bool + right_endpoint: EntityIdWithInterval = Field(..., alias='rightEndpoint') + +class OntologyOutwardEdge(RootModel[OntologyToOntologyOutwardEdge | OntologyToKnowledgeGraphOutwardEdge]): + model_config = ConfigDict(populate_by_name=True) + root: OntologyToOntologyOutwardEdge | OntologyToKnowledgeGraphOutwardEdge + +class EntityTypeVertex(BaseModel): + model_config = ConfigDict(populate_by_name=True) + inner: EntityTypeWithMetadata + kind: Literal['entityType'] + +class VariableDecisionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: DecisionTime + interval: RightBoundedTemporalInterval + +class QueryTemporalAxesDecisionTime(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pinned: PinnedTransactionAxis = Field(..., title='PinnedTransactionAxis') + variable: VariableDecisionAxis = Field(..., title='VariableDecisionAxis') + +class VariableTransactionAxis(BaseModel): + model_config = ConfigDict(populate_by_name=True) + axis: TransactionTime + interval: RightBoundedTemporalInterval + +class QueryTemporalAxesTransactionTime(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pinned: PinnedDecisionAxis = Field(..., title='PinnedDecisionAxis') + variable: VariableTransactionAxis = Field(..., title='VariableTransactionAxis') + +class QueryTemporalAxes(RootModel[QueryTemporalAxesDecisionTime | QueryTemporalAxesTransactionTime]): + model_config = ConfigDict(populate_by_name=True) + root: QueryTemporalAxesDecisionTime | QueryTemporalAxesTransactionTime = Field(..., description='Defines the two possible combinations of pinned/variable temporal axes that are used in\nresponses to queries that return [`Subgraph`]s.\n\nWhen querying the Graph, temporal data is returned. The Graph is implemented as a bitemporal\ndata store, which means the knowledge data contains information about the time of when the\nknowledge was inserted into the Graph, the [`TransactionTime`], and when the knowledge was\ndecided to be inserted, the [`DecisionTime`].\n\nIn order to query data from the Graph, only one of the two time axes can be used. This is\nachieved by using a `TemporalAxes`. The `TemporalAxes` pins one axis to a specified\n[`Timestamp`], while the other axis can be a [`Interval`]. The pinned axis is called the\n[`PinnedTemporalAxis`] and the other axis is called the [`VariableTemporalAxis`]. The returned\ndata will then only contain temporal data that is contained in the [`Interval`] of the\n[`VariableTemporalAxis`] for the given [`Timestamp`] of the [`PinnedTemporalAxis`].\n\n[`Subgraph`]: crate::subgraph::Subgraph\n[`Interval`]: temporal_versioning::Interval') + +class SubgraphTemporalAxes(BaseModel): + model_config = ConfigDict(populate_by_name=True) + initial: QueryTemporalAxesUnresolved + resolved: QueryTemporalAxes + +class DataTypeWithMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + metadata: OntologyElementMetadata + schema_: DataType = Field(..., alias='schema') + +class Edges(RootModel[dict[str, dict[str, list[OntologyOutwardEdge | KnowledgeGraphOutwardEdge]]] | None]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, dict[str, list[OntologyOutwardEdge | KnowledgeGraphOutwardEdge]]] | None = None + +class EntityMetadata(BaseModel): + """ + The metadata of an [`Entity`] record. + """ + model_config = ConfigDict(populate_by_name=True) + archived: bool + draft: bool + entity_type_id: str = Field(..., alias='entityTypeId') + provenance: ProvenanceMetadata + record_id: EntityRecordId = Field(..., alias='recordId') + temporal_versioning: EntityTemporalMetadata = Field(..., alias='temporalVersioning') + +class MaybeListOfOntologyElementMetadata(RootModel[OntologyElementMetadata | list[OntologyElementMetadata]]): + model_config = ConfigDict(populate_by_name=True) + root: OntologyElementMetadata | list[OntologyElementMetadata] + +class DataTypeVertex(BaseModel): + model_config = ConfigDict(populate_by_name=True) + inner: DataTypeWithMetadata + kind: Literal['dataType'] + +class Entity(BaseModel): + """ + A record of an [`Entity`] that has been persisted in the datastore, with its associated + metadata. + """ + model_config = ConfigDict(populate_by_name=True) + link_data: LinkData | None = Field(None, alias='linkData') + metadata: EntityMetadata + properties: EntityProperties + +class EntityVertex(BaseModel): + model_config = ConfigDict(populate_by_name=True) + inner: Entity + kind: Literal['entity'] + +class KnowledgeGraphVertex(RootModel[EntityVertex]): + model_config = ConfigDict(populate_by_name=True) + root: EntityVertex = Field(..., discriminator='kind') + +class KnowledgeGraphVertices(RootModel[dict[str, dict[str, KnowledgeGraphVertex]] | None]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, dict[str, KnowledgeGraphVertex]] | None = None + +class CreatePropertyTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + owned_by_id: OwnedById = Field(..., alias='ownedById') + schema_: PropertyType | list[PropertyType] = Field(..., alias='schema') + +class DataTypeStructuralQuery(BaseModel): + model_config = ConfigDict(populate_by_name=True) + filter: Filter + graph_resolve_depths: GraphResolveDepths = Field(..., alias='graphResolveDepths') + temporal_axes: QueryTemporalAxesUnresolved = Field(..., alias='temporalAxes') + +class EntityStructuralQuery(BaseModel): + model_config = ConfigDict(populate_by_name=True) + filter: Filter + graph_resolve_depths: GraphResolveDepths = Field(..., alias='graphResolveDepths') + temporal_axes: QueryTemporalAxesUnresolved = Field(..., alias='temporalAxes') + +class EntityTypeStructuralQuery(BaseModel): + model_config = ConfigDict(populate_by_name=True) + filter: Filter + graph_resolve_depths: GraphResolveDepths = Field(..., alias='graphResolveDepths') + temporal_axes: QueryTemporalAxesUnresolved = Field(..., alias='temporalAxes') + +class AllFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + all: list[Filter] + +class AnyFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + any: list[Filter] + +class NotFilter(BaseModel): + model_config = ConfigDict(populate_by_name=True) + not_: Filter = Field(..., alias='not') + +class Filter(RootModel[AllFilter | AnyFilter | NotFilter | EqualFilter | NotEqualFilter | StartsWithFilter | EndsWithFilter | ContainsSegmentFilter]): + model_config = ConfigDict(populate_by_name=True) + root: AllFilter | AnyFilter | NotFilter | EqualFilter | NotEqualFilter | StartsWithFilter | EndsWithFilter | ContainsSegmentFilter + +class LoadExternalPropertyTypeRequestItem1(BaseModel): + model_config = ConfigDict(populate_by_name=True) + schema_: PropertyType = Field(..., alias='schema') + +class LoadExternalPropertyTypeRequest(RootModel[LoadExternalPropertyTypeRequestItem | LoadExternalPropertyTypeRequestItem1]): + model_config = ConfigDict(populate_by_name=True) + root: LoadExternalPropertyTypeRequestItem | LoadExternalPropertyTypeRequestItem1 + +class PropertyTypeVertex(BaseModel): + model_config = ConfigDict(populate_by_name=True) + inner: PropertyTypeWithMetadata + kind: Literal['propertyType'] + +class OntologyVertex(RootModel[DataTypeVertex | PropertyTypeVertex | EntityTypeVertex]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeVertex | PropertyTypeVertex | EntityTypeVertex = Field(..., discriminator='kind') + +class OntologyVertices(RootModel[dict[str, dict[str, OntologyVertex]] | None]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, dict[str, OntologyVertex]] | None = None + +class PropertyTypeStructuralQuery(BaseModel): + model_config = ConfigDict(populate_by_name=True) + filter: Filter + graph_resolve_depths: GraphResolveDepths = Field(..., alias='graphResolveDepths') + temporal_axes: QueryTemporalAxesUnresolved = Field(..., alias='temporalAxes') + +class PropertyTypeWithMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + metadata: OntologyElementMetadata + schema_: PropertyType = Field(..., alias='schema') + +class Subgraph(BaseModel): + model_config = ConfigDict(populate_by_name=True) + depths: GraphResolveDepths + edges: Edges + roots: list[GraphElementVertexId] + temporal_axes: SubgraphTemporalAxes = Field(..., alias='temporalAxes') + vertices: Vertices + +class UpdatePropertyTypeRequest(BaseModel): + model_config = ConfigDict(populate_by_name=True) + schema_: UpdatePropertyType = Field(..., alias='schema') + type_to_update: VersionedURL = Field(..., alias='typeToUpdate') + +class Vertex(RootModel[OntologyVertex | KnowledgeGraphVertex]): + model_config = ConfigDict(populate_by_name=True) + root: OntologyVertex | KnowledgeGraphVertex + +class Vertices(RootModel[dict[str, dict[str, KnowledgeGraphVertex | OntologyVertex]] | None]): + model_config = ConfigDict(populate_by_name=True) + root: dict[str, dict[str, KnowledgeGraphVertex | OntologyVertex]] | None = None + +class Items(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + one_of: list[PropertyValues] = Field(..., alias='oneOf', min_length=1) + +class PropertyArrayValue(BaseModel): + model_config = ConfigDict(extra='forbid', populate_by_name=True) + type: Literal['array'] + items: Items + min_items: int | None = Field(None, alias='minItems', ge=0) + max_items: int | None = Field(None, alias='maxItems', ge=0) + +class PropertyValues(RootModel[DataTypeReference | PropertyObjectValue | PropertyArrayValue]): + model_config = ConfigDict(populate_by_name=True) + root: DataTypeReference | PropertyObjectValue | PropertyArrayValue = Field(..., description='The definition of potential property values, either references to data types, objects made up of more property types, or an array where the items are defined from a set of other property values definitions.', title='propertyValues') + +class PropertyType(OntologyTypeSchema): + """ + Specifies the structure of a Block Protocol property type + """ + model_config = ConfigDict(extra='forbid', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/property-type'] = Field(..., alias='$schema') + kind: Literal['propertyType'] + identifier: VersionedURL = Field(..., alias='$id') + title: str + description: str | None = None + one_of: list[PropertyValues] = Field(..., alias='oneOf') + +class UpdatePropertyType(BaseModel): + """ + The contents of a Property Type update request + """ + model_config = ConfigDict(extra='forbid', populate_by_name=True) + schema_url: Literal['https://blockprotocol.org/types/modules/graph/0.3/schema/property-type'] = Field(..., alias='$schema') + kind: Literal['propertyType'] + title: str + description: str | None = None + one_of: list[PropertyValues] = Field(..., alias='oneOf') +CreatePropertyTypeRequest.model_rebuild() +DataTypeStructuralQuery.model_rebuild() +EntityStructuralQuery.model_rebuild() +EntityTypeStructuralQuery.model_rebuild() +AllFilter.model_rebuild() +AnyFilter.model_rebuild() +NotFilter.model_rebuild() +LoadExternalPropertyTypeRequestItem1.model_rebuild() +PropertyTypeVertex.model_rebuild() +PropertyTypeWithMetadata.model_rebuild() +Subgraph.model_rebuild() +UpdatePropertyTypeRequest.model_rebuild() +Items.model_rebuild() \ No newline at end of file diff --git a/libs/hash-graph-client/python/graph_client/py.typed b/libs/hash-graph-client/python/graph_client/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/libs/hash-graph-client/python/graph_client/schema.py b/libs/hash-graph-client/python/graph_client/schema.py new file mode 100644 index 0000000..f01032e --- /dev/null +++ b/libs/hash-graph-client/python/graph_client/schema.py @@ -0,0 +1,13 @@ +"""Base classes for all schemas.""" + +from abc import ABC + +from pydantic import BaseModel + + +class Schema(BaseModel, ABC): + """Base class for all schemas.""" + + +class OntologyTypeSchema(Schema, ABC): + """Base class for all ontology type schemas.""" diff --git a/libs/hash-graph-client/python/package.json b/libs/hash-graph-client/python/package.json new file mode 100644 index 0000000..603b998 --- /dev/null +++ b/libs/hash-graph-client/python/package.json @@ -0,0 +1,25 @@ +{ + "name": "@local/hash-graph-client-py", + "version": "0.0.0-private", + "private": true, + "description": "Type definitions for the type system and entity validation based on schemas", + "scripts": { + "build": "poetry build --no-interaction", + "codegen": "./scripts/codegen.sh", + "fix:black": "poetry run black graph_client", + "fix:lock-files": "poetry lock --no-update", + "fix:ruff": "poetry run ruff graph_client --fix", + "lint:black": "poetry run black --check --diff --color graph_client", + "lint:lock-files": "poetry lock --check", + "lint:mypy": "poetry run mypy .", + "lint:ruff": "poetry run ruff graph_client", + "poetry:install": "poetry install --no-root --no-interaction", + "poetry:install-production": "poetry install --no-root --no-interaction --only main" + }, + "dependencies": { + "@apps/hash-graph": "0.0.0-private" + }, + "devDependencies": { + "@redocly/cli": "1.4.1" + } +} diff --git a/libs/hash-graph-client/python/poetry.lock b/libs/hash-graph-client/python/poetry.lock new file mode 100644 index 0000000..6cd4dc4 --- /dev/null +++ b/libs/hash-graph-client/python/poetry.lock @@ -0,0 +1,1344 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[[package]] +name = "anyio" +version = "3.7.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + +[[package]] +name = "argcomplete" +version = "3.1.1" +description = "Bash tab completion for argparse" +optional = false +python-versions = ">=3.6" +files = [ + {file = "argcomplete-3.1.1-py3-none-any.whl", hash = "sha256:35fa893a88deea85ea7b20d241100e64516d6af6d7b0ae2bed1d263d26f70948"}, + {file = "argcomplete-3.1.1.tar.gz", hash = "sha256:6c4c563f14f01440aaffa3eae13441c5db2357b5eec639abe7c0b15334627dff"}, +] + +[package.extras] +test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "black" +version = "23.10.1" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, + {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, + {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, + {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, + {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, + {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, + {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, + {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, + {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, + {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, + {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.6" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, + {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "datamodel-code-generator" +version = "0.22.1" +description = "Datamodel Code Generator" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "datamodel_code_generator-0.22.1-py3-none-any.whl", hash = "sha256:ac1fbc4fa778c2a43f740740fd352ca4300f705044e112a0023af8d04f0b61af"}, + {file = "datamodel_code_generator-0.22.1.tar.gz", hash = "sha256:48c8ce0b38b575bcc573237bb3faab696b072aa131b3f008c848d2c3b24a4417"}, +] + +[package.dependencies] +argcomplete = ">=1.10,<4.0" +black = ">=19.10b0" +genson = ">=1.2.1,<2.0" +inflect = ">=4.1.0,<6.0" +isort = ">=4.3.21,<6.0" +jinja2 = ">=2.10.1,<4.0" +openapi-spec-validator = ">=0.2.8,<=0.5.7" +packaging = "*" +prance = ">=0.18.2" +pydantic = {version = ">=1.10.0,<2.4.0 || >2.4.0,<3.0", extras = ["email"], markers = "python_version >= \"3.11\" and python_version < \"4.0\""} +PySnooper = ">=0.4.1,<2.0.0" +toml = ">=0.10.0,<1.0.0" + +[package.extras] +http = ["httpx"] + +[[package]] +name = "dnspython" +version = "2.4.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "dnspython-2.4.1-py3-none-any.whl", hash = "sha256:5b7488477388b8c0b70a8ce93b227c5603bc7b77f1565afe8e729c36c51447d7"}, + {file = "dnspython-2.4.1.tar.gz", hash = "sha256:c33971c79af5be968bb897e95c2448e11a645ee84d93b265ce0b7aabe5dfdca8"}, +] + +[package.extras] +dnssec = ["cryptography (>=2.6,<42.0)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=0.17.3)", "httpx (>=0.24.1)"] +doq = ["aioquic (>=0.9.20)"] +idna = ["idna (>=2.1,<4.0)"] +trio = ["trio (>=0.14,<0.23)"] +wmi = ["wmi (>=1.5.1,<2.0.0)"] + +[[package]] +name = "email-validator" +version = "2.0.0.post2" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.7" +files = [ + {file = "email_validator-2.0.0.post2-py3-none-any.whl", hash = "sha256:2466ba57cda361fb7309fd3d5a225723c788ca4bbad32a0ebd5373b99730285c"}, + {file = "email_validator-2.0.0.post2.tar.gz", hash = "sha256:1ff6e86044200c56ae23595695c54e9614f4a9551e0e393614f764860b3d7900"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + +[[package]] +name = "genson" +version = "1.2.2" +description = "GenSON is a powerful, user-friendly JSON Schema generator." +optional = false +python-versions = "*" +files = [ + {file = "genson-1.2.2.tar.gz", hash = "sha256:8caf69aa10af7aee0e1a1351d1d06801f4696e005f06cedef438635384346a16"}, +] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "0.18.0" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"}, + {file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"}, +] + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = "==1.*" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "httpx" +version = "0.25.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"}, + {file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"}, +] + +[package.dependencies] +certifi = "*" +httpcore = ">=0.18.0,<0.19.0" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "inflect" +version = "5.6.2" +description = "Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words" +optional = false +python-versions = ">=3.7" +files = [ + {file = "inflect-5.6.2-py3-none-any.whl", hash = "sha256:b45d91a4a28a4e617ff1821117439b06eaa86e2a4573154af0149e9be6687238"}, + {file = "inflect-5.6.2.tar.gz", hash = "sha256:aadc7ed73928f5e014129794bbac03058cca35d0a973a5fc4eb45c7fa26005f9"}, +] + +[package.extras] +docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] +testing = ["pygments", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.17.3" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, + {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-spec" +version = "0.1.6" +description = "JSONSchema Spec with object-oriented paths" +optional = false +python-versions = ">=3.7.0,<4.0.0" +files = [ + {file = "jsonschema_spec-0.1.6-py3-none-any.whl", hash = "sha256:f2206d18c89d1824c1f775ba14ed039743b41a9167bd2c5bdb774b66b3ca0bbf"}, + {file = "jsonschema_spec-0.1.6.tar.gz", hash = "sha256:90215863b56e212086641956b20127ccbf6d8a3a38343dad01d6a74d19482f76"}, +] + +[package.dependencies] +jsonschema = ">=4.0.0,<4.18.0" +pathable = ">=0.4.1,<0.5.0" +PyYAML = ">=5.1" +requests = ">=2.31.0,<3.0.0" + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "openapi-schema-validator" +version = "0.4.4" +description = "OpenAPI schema validation for Python" +optional = false +python-versions = ">=3.7.0,<4.0.0" +files = [ + {file = "openapi_schema_validator-0.4.4-py3-none-any.whl", hash = "sha256:79f37f38ef9fd5206b924ed7a6f382cea7b649b3b56383c47f1906082b7b9015"}, + {file = "openapi_schema_validator-0.4.4.tar.gz", hash = "sha256:c573e2be2c783abae56c5a1486ab716ca96e09d1c3eab56020d1dc680aa57bf8"}, +] + +[package.dependencies] +jsonschema = ">=4.0.0,<4.18.0" +rfc3339-validator = "*" + +[package.extras] +docs = ["sphinx (>=5.3.0,<6.0.0)", "sphinx-immaterial (>=0.11.0,<0.12.0)"] + +[[package]] +name = "openapi-spec-validator" +version = "0.5.2" +description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3 spec validator" +optional = false +python-versions = ">=3.7.0,<4.0.0" +files = [ + {file = "openapi_spec_validator-0.5.2-py3-none-any.whl", hash = "sha256:1f8db08ecbcf4ec8c558d65b65b3b7b428f81da6642f2f163e992ae3e17b229c"}, + {file = "openapi_spec_validator-0.5.2.tar.gz", hash = "sha256:ebed7f1c567780859402ad64b128e17f519d15f605f1b41d1e9a4a7a1690be07"}, +] + +[package.dependencies] +jsonschema = ">=4.0.0,<5.0.0" +jsonschema-spec = ">=0.1.1,<0.2.0" +lazy-object-proxy = ">=1.7.1,<2.0.0" +openapi-schema-validator = ">=0.3.2,<0.5" + +[package.extras] +requests = ["requests"] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pathable" +version = "0.4.3" +description = "Object-oriented paths" +optional = false +python-versions = ">=3.7.0,<4.0.0" +files = [ + {file = "pathable-0.4.3-py3-none-any.whl", hash = "sha256:cdd7b1f9d7d5c8b8d3315dbf5a86b2596053ae845f056f57d97c0eefff84da14"}, + {file = "pathable-0.4.3.tar.gz", hash = "sha256:5c869d315be50776cc8a993f3af43e0c60dc01506b399643f919034ebf4cdcab"}, +] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "prance" +version = "23.6.21.0" +description = "Resolving Swagger/OpenAPI 2.0 and 3.0.0 Parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "prance-23.6.21.0-py3-none-any.whl", hash = "sha256:6a4276fa07ed9f22feda4331097d7503c4adc3097e46ffae97425f2c1026bd9f"}, + {file = "prance-23.6.21.0.tar.gz", hash = "sha256:d8c15f8ac34019751cc4945f866d8d964d7888016d10de3592e339567177cabe"}, +] + +[package.dependencies] +chardet = ">=3.0" +packaging = ">=21.3" +requests = ">=2.25" +"ruamel.yaml" = ">=0.17.10" +six = ">=1.15,<2.0" + +[package.extras] +cli = ["click (>=7.0)"] +dev = ["bumpversion (>=0.6)", "pytest (>=6.1)", "pytest-cov (>=2.11)", "sphinx (>=3.4)", "towncrier (>=19.2)", "tox (>=3.4)"] +flex = ["flex (>=6.13,<7.0)"] +icu = ["PyICU (>=2.4,<3.0)"] +osv = ["openapi-spec-validator (>=0.5.1,<0.6.0)"] +ssv = ["swagger-spec-validator (>=2.4,<3.0)"] + +[[package]] +name = "pydantic" +version = "2.4.2" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, + {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""} +pydantic-core = "2.10.1" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.10.1" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, + {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, + {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, + {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, + {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, + {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, + {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, + {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, + {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, + {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, + {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, + {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, + {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, + {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, + {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, + {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, + {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, + {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, + {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, + {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, + {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, +] + +[[package]] +name = "pysnooper" +version = "1.2.0" +description = "A poor man's debugger for Python." +optional = false +python-versions = "*" +files = [ + {file = "PySnooper-1.2.0-py2.py3-none-any.whl", hash = "sha256:aa859aa9a746cffc1f35e4ee469d49c3cc5185b5fc0c571feb3af3c94d2eb625"}, + {file = "PySnooper-1.2.0.tar.gz", hash = "sha256:810669e162a250a066d8662e573adbc5af770e937c5b5578f28bb7355d1c859b"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "ruamel-yaml" +version = "0.17.32" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +optional = false +python-versions = ">=3" +files = [ + {file = "ruamel.yaml-0.17.32-py3-none-any.whl", hash = "sha256:23cd2ed620231677564646b0c6a89d138b6822a0d78656df7abda5879ec4f447"}, + {file = "ruamel.yaml-0.17.32.tar.gz", hash = "sha256:ec939063761914e14542972a5cba6d33c23b0859ab6342f61cf070cfc600efc2"}, +] + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.12\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.7" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +optional = false +python-versions = ">=3.5" +files = [ + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, + {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, +] + +[[package]] +name = "ruff" +version = "0.1.2" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.2-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:0d3ee66b825b713611f89aa35d16de984f76f26c50982a25d52cd0910dff3923"}, + {file = "ruff-0.1.2-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f85f850a320ff532b8f93e8d1da6a36ef03698c446357c8c43b46ef90bb321eb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:809c6d4e45683696d19ca79e4c6bd3b2e9204fe9546923f2eb3b126ec314b0dc"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46005e4abb268e93cad065244e17e2ea16b6fcb55a5c473f34fbc1fd01ae34cb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10cdb302f519664d5e2cf954562ac86c9d20ca05855e5b5c2f9d542228f45da4"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f89ebcbe57a1eab7d7b4ceb57ddf0af9ed13eae24e443a7c1dc078000bd8cc6b"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7344eaca057d4c32373c9c3a7afb7274f56040c225b6193dd495fcf69453b436"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dffa25f6e03c4950b6ac6f216bc0f98a4be9719cb0c5260c8e88d1bac36f1683"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42ddaea52cb7ba7c785e8593a7532866c193bc774fe570f0e4b1ccedd95b83c5"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8533efda625bbec0bf27da2886bd641dae0c209104f6c39abc4be5b7b22de2a"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b0b1b82221ba7c50e03b7a86b983157b5d3f4d8d4f16728132bdf02c6d651f77"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c1362eb9288f8cc95535294cb03bd4665c8cef86ec32745476a4e5c6817034c"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ffa7ef5ded0563329a35bd5a1cfdae40f05a75c0cc2dd30f00b1320b1fb461fc"}, + {file = "ruff-0.1.2-py3-none-win32.whl", hash = "sha256:6e8073f85e47072256e2e1909f1ae515cf61ff5a4d24730a63b8b4ac24b6704a"}, + {file = "ruff-0.1.2-py3-none-win_amd64.whl", hash = "sha256:b836ddff662a45385948ee0878b0a04c3a260949905ad861a37b931d6ee1c210"}, + {file = "ruff-0.1.2-py3-none-win_arm64.whl", hash = "sha256:b0c42d00db5639dbd5f7f9923c63648682dd197bf5de1151b595160c96172691"}, + {file = "ruff-0.1.2.tar.gz", hash = "sha256:afd4785ae060ce6edcd52436d0c197628a918d6d09e3107a892a1bad6a4c6608"}, +] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "urllib3" +version = "2.0.4" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, + {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "d70d80d07934230ece43c57b5fbf6318dd2a46d59d97e28e98d8b16a777d696e" diff --git a/libs/hash-graph-client/python/poetry.toml b/libs/hash-graph-client/python/poetry.toml new file mode 100644 index 0000000..a5f04e6 --- /dev/null +++ b/libs/hash-graph-client/python/poetry.toml @@ -0,0 +1,3 @@ +[virtualenvs] +name = ".venv" +in-project = true diff --git a/libs/hash-graph-client/python/pyproject.toml b/libs/hash-graph-client/python/pyproject.toml new file mode 100644 index 0000000..a9fdc63 --- /dev/null +++ b/libs/hash-graph-client/python/pyproject.toml @@ -0,0 +1,91 @@ +[tool.poetry] +name = "hash-graph-client" +version = "0.0.0" +description = "OpenAPI client for the HASH Graph API" +license = "AGPL-3.0-only" +authors = ["HASH"] +readme = "README.md" +packages = [{ include = "graph_client" }] + +[tool.poetry.dependencies] +python = "^3.11" + +pydantic = "^2.4.2" +httpx = "^0.25.0" +yarl = "^1.9.2" + +[tool.poetry.group.dev.dependencies] +setuptools = "^68.2.2" +datamodel-code-generator = "^0.22.1" + +[tool.poetry.group.lint-tools.dependencies] +black = "^23.10.1" +ruff = "^0.1.2" +mypy = "^1.6.1" + + +[tool.black] +target-version = ['py311'] +preview = true +extend-exclude = ''' +( + ^/graph_client/models.py +) +''' + +[tool.ruff] +select = ["ALL"] +ignore = [ + "D203", # this conflicts with `D211` + "D213", # this conflicts with `D212` + "D401", # Relates to PEP-257 but also conflicts with Google Python Style Guide, generally gets in the way + "ANN101", # most type checkers infer the type of `self` automatically + "ANN102", # most type checkers infer the type of `cls` automatically + "FIX002", # TODOs should be fixed, not removed + "TD002", # We don't add authors to TODO strings + "PLC0414", # Conflicts with `no_implicit_reexport = true` +] + +target-version = "py311" + +extend-exclude = [ + "graph_client/models.py" +] + +[tool.mypy] +plugins = "pydantic.mypy" + +disallow_untyped_defs = true +disallow_any_unimported = true +no_implicit_optional = true +check_untyped_defs = true +no_implicit_reexport = true +strict_optional = true +show_error_codes = true +show_traceback = true +strict_equality = true + +# warnings +warn_unused_configs = true +warn_return_any = true +warn_incomplete_stub = true +warn_unreachable = true +warn_redundant_casts = true +warn_unused_ignores = true + +# error messages +pretty = true +color_output = true +error_summary = true +incremental = true + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/libs/hash-graph-client/python/scripts/aliases.json b/libs/hash-graph-client/python/scripts/aliases.json new file mode 100644 index 0000000..cb46eb8 --- /dev/null +++ b/libs/hash-graph-client/python/scripts/aliases.json @@ -0,0 +1,4 @@ +{ + "$id": "identifier", + "$schema": "schema_url" +} diff --git a/libs/hash-graph-client/python/scripts/codegen.sh b/libs/hash-graph-client/python/scripts/codegen.sh new file mode 100755 index 0000000..fc0facd --- /dev/null +++ b/libs/hash-graph-client/python/scripts/codegen.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Thanks to: https://stackoverflow.com/a/246128/9077988 +SOURCE=${BASH_SOURCE[0]} +while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd ) + SOURCE=$(readlink "$SOURCE") + [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd ) + +SPEC_DIR="$DIR/../../../../../apps/hash-graph/openapi" +SPEC="$SPEC_DIR/openapi.json" + +# cd up to the package directory (needed for poetry and yarn) +cd "$DIR/.." + +poetry run datamodel-codegen --version + +# Take the specification and bundle all models into a single file +yarn run redocly bundle --format=json "$SPEC" -o "$DIR/openapi.bundle.json" + +# we need to do a bit of plumbing, this includes: +# merging `PropertyObjectReference` from `models/shared.json` into components.schemas, renaming all `#/definitions/` to `#/components/schemas/` (redocly ignores `x-patternProperties` and `patternProeprties`) +# renaming `x-patternProperties` to `patternProperties`. +SHARED_MODELS="$SPEC_DIR/models/shared.json" +jq -s ' + .[0].components.schemas.PropertyObjectReference = .[1].definitions.PropertyObjectReference + | .[0] + | walk( if type == "string" then sub("^#/definitions/"; "#/components/schemas/") else . end ) + | walk( if type == "object" and has("x-patternProperties") then .patternProperties = .["x-patternProperties"] | del(.["x-patternProperties"]) else . end ) + ' "$DIR/openapi.bundle.json" "$SHARED_MODELS" > "$DIR/openapi.bundle.json.tmp" +mv "$DIR/openapi.bundle.json.tmp" "$DIR/openapi.bundle.json" + +poetry run datamodel-codegen \ + --input "$DIR/openapi.bundle.json" \ + --output graph_client/models.py \ + --output-model-type pydantic_v2.BaseModel \ + --input-file-type openapi \ + --use-standard-collections \ + --use-union-operator \ + --target-python-version 3.11 \ + --use-schema-description \ + --snake-case-field \ + --disable-timestamp \ + --enable-version-header \ + --enum-field-as-literal one \ + --use-double-quotes \ + --field-constraints \ + --allow-population-by-field-name \ + --strict-nullable \ + --use-title-as-name \ + --aliases "$DIR/aliases.json" + +poetry run python "$DIR/rebase.py" diff --git a/libs/hash-graph-client/python/scripts/rebase.py b/libs/hash-graph-client/python/scripts/rebase.py new file mode 100644 index 0000000..d6574ac --- /dev/null +++ b/libs/hash-graph-client/python/scripts/rebase.py @@ -0,0 +1,37 @@ +# use AST transformations to rewrite the `models.py`, so that +# A) `models.py` imports `schema.py` +# B) `models.py` `EntityType`, `PropertyType` and `DataType` +# inherit from `OntologyTypeSchema` + +import ast +from pathlib import Path + +DIRECTORY = Path(__file__).parent.parent + +import_statement = ast.ImportFrom( + module="graph_client.schema", names=[(ast.alias(name="OntologyTypeSchema"))] +) + + +def remap(class_def: ast.ClassDef) -> ast.ClassDef: + """Remap the class base class to `OntologyTypeSchema`.""" + if class_def.name not in ("EntityType", "PropertyType", "DataType"): + return class_def + + class_def.bases = [ast.Name(id="OntologyTypeSchema", ctx=ast.Load())] + return class_def + + +models = DIRECTORY / "graph_client" / "models.py" + +contents = models.read_text() +tree = ast.parse(contents) + +for node in ast.walk(tree): + if isinstance(node, ast.ClassDef): + remap(node) + +tree.body.insert(1, import_statement) + +contents = ast.unparse(ast.fix_missing_locations(tree)) +models.write_text(contents) diff --git a/libs/hash-graph-client/python/turbo.json b/libs/hash-graph-client/python/turbo.json new file mode 100644 index 0000000..25d03f5 --- /dev/null +++ b/libs/hash-graph-client/python/turbo.json @@ -0,0 +1,49 @@ +{ + "extends": ["//"], + "pipeline": { + "codegen": { + "inputs": [ + "../../../../apps/hash-graph/openapi/openapi.json", + "./scripts/codegen.sh" + ], + "outputs": ["./graph_client/models.py"] + }, + "build": { + "dependsOn": ["^build", "codegen"], + "inputs": ["./**/*.py", "pyproject.toml", "poetry.lock", "LICENSE*"], + "outputs": ["dist/**"] + }, + "poetry:venv": { + "cache": false + }, + "poetry:install": { + "cache": false + }, + "poetry:install-production": { + "cache": false + }, + "fix:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"], + "outputs": ["poetry.lock"] + }, + "lint:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"] + }, + "lint:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:mypy": { + "dependsOn": ["build"], + "inputs": ["./**/*.py", "pyproject.toml"] + } + } +} diff --git a/libs/hash-graph-client/python/yarn.lock b/libs/hash-graph-client/python/yarn.lock new file mode 100644 index 0000000..d364a6a --- /dev/null +++ b/libs/hash-graph-client/python/yarn.lock @@ -0,0 +1,314 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@apidevtools/json-schema-ref-parser@9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" + integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== + dependencies: + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + js-yaml "^3.13.1" + +"@apidevtools/openapi-schemas@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" + integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== + +"@apidevtools/swagger-cli@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-cli/-/swagger-cli-4.0.4.tgz#c645c291f56e4add583111aca9edeee23d60fa10" + integrity sha512-hdDT3B6GLVovCsRZYDi3+wMcB1HfetTU20l2DC8zD3iFRNMC6QNAZG5fo/6PYeHWBEv7ri4MvnlKodhNB0nt7g== + dependencies: + "@apidevtools/swagger-parser" "^10.0.1" + chalk "^4.1.0" + js-yaml "^3.14.0" + yargs "^15.4.1" + +"@apidevtools/swagger-methods@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== + +"@apidevtools/swagger-parser@^10.0.1": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz#a987d71e5be61feb623203be0c96e5985b192ab6" + integrity sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw== + dependencies: + "@apidevtools/json-schema-ref-parser" "9.0.6" + "@apidevtools/openapi-schemas" "^2.1.0" + "@apidevtools/swagger-methods" "^3.0.2" + "@jsdevtools/ono" "^7.1.3" + ajv "^8.6.3" + ajv-draft-04 "^1.0.0" + call-me-maybe "^1.0.1" + +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + +ajv-draft-04@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + +ajv@^8.6.3: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +call-me-maybe@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +js-yaml@^3.13.1, js-yaml@^3.14.0: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" diff --git a/libs/hash-graph-sdk/python/.gitattributes b/libs/hash-graph-sdk/python/.gitattributes new file mode 100644 index 0000000..d03f222 --- /dev/null +++ b/libs/hash-graph-sdk/python/.gitattributes @@ -0,0 +1,2 @@ +./graph_sdk/filter/path.py linguist-generate=true +./graph_sdk/client/blocking.py linguist-generate=true diff --git a/libs/hash-graph-sdk/python/LICENSE.md b/libs/hash-graph-sdk/python/LICENSE.md new file mode 100644 index 0000000..9a70d79 --- /dev/null +++ b/libs/hash-graph-sdk/python/LICENSE.md @@ -0,0 +1,606 @@ +# GNU Affero General Public License + +_Version 3, 19 November 2007_ +_Copyright © 2007 Free Software Foundation, Inc. <>_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +## Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: **(1)** assert copyright on the software, and **(2)** offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions + +“This License” refers to version 3 of the GNU Affero General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based +on the Program. + +To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that **(1)** displays an appropriate copyright notice, and **(2)** +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code + +The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work. + +A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other +than the work as a whole, that **(a)** is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and **(b)** serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +### 2. Basic Permissions + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +### 4. Conveying Verbatim Copies + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +- **a)** The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- **b)** The work must carry prominent notices stating that it is + released under this License and any conditions added under section 7. + This requirement modifies the requirement in section 4 to + “keep intact all notices”. +- **c)** You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- **d)** If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +- **a)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- **b)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either **(1)** a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or **(2)** access to copy the + Corresponding Source from a network server at no charge. +- **c)** Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- **d)** Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- **e)** Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A “User Product” is either **(1)** a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or **(2)** anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms + +“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +- **a)** Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- **b)** Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- **c)** Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- **d)** Limiting the use for publicity purposes of names of licensors or + authors of the material; or +- **e)** Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- **f)** Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + +All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +### 8. Termination + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated **(a)** +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and **(b)** permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents + +A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either **(1)** cause the Corresponding Source to be so +available, or **(2)** arrange to deprive yourself of the benefit of the +patent license for this particular work, or **(3)** arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license **(a)** in connection with copies of the covered work +conveyed by you (or copies made from those copies), or **(b)** primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16 + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. diff --git a/libs/hash-graph-sdk/python/README.md b/libs/hash-graph-sdk/python/README.md new file mode 100644 index 0000000..ef55bf4 --- /dev/null +++ b/libs/hash-graph-sdk/python/README.md @@ -0,0 +1,3 @@ +# HASH Graph API SDK + +High-level interface for the HASH Graph API, providing several convenience methods for interacting with the API. diff --git a/libs/hash-graph-sdk/python/examples/query_company_entities.py b/libs/hash-graph-sdk/python/examples/query_company_entities.py new file mode 100644 index 0000000..878c5fc --- /dev/null +++ b/libs/hash-graph-sdk/python/examples/query_company_entities.py @@ -0,0 +1,24 @@ +from uuid import UUID + +import devtools +from yarl import URL + +from graph_sdk.client.blocking import HASHClient +from graph_sdk.filter import EntityQueryPath +from graph_sdk.options import Options +from graph_sdk.query import Parameter +from graph_sdk.utils import filter_latest_from_subgraph + +COMPANY_URL = "https://blockprotocol.org/@examples/types/entity-type/company/" +ACTOR_ID = UUID(int=0) # replace with your actor ID + +client = HASHClient(URL("http://localhost:4000/"), actor=ACTOR_ID) + +subgraph = client.query_entities( + EntityQueryPath().type_().base_url() == Parameter(COMPANY_URL), + Options(), +) + +buildings = filter_latest_from_subgraph(subgraph) + +devtools.pprint(buildings) diff --git a/libs/hash-graph-sdk/python/examples/query_company_entities_limited_axes.py b/libs/hash-graph-sdk/python/examples/query_company_entities_limited_axes.py new file mode 100644 index 0000000..7d96c36 --- /dev/null +++ b/libs/hash-graph-sdk/python/examples/query_company_entities_limited_axes.py @@ -0,0 +1,35 @@ +from datetime import datetime +from uuid import UUID + +import devtools +from yarl import URL + +from graph_sdk.client.blocking import HASHClient +from graph_sdk.filter import EntityQueryPath +from graph_sdk.options import ( + Options, + TemporalAxesBuilder, + TemporalBound, +) +from graph_sdk.query import Parameter +from graph_sdk.utils import filter_latest_from_subgraph + +COMPANY_URL = "https://blockprotocol.org/@examples/types/entity-type/company/" +ACTOR_ID = UUID(int=0) # replace with your actor ID + +client = HASHClient(URL("http://localhost:4000/"), actor=ACTOR_ID) + +options = Options() +options.temporal_axes = TemporalAxesBuilder.pinned_transaction_time(None).between( + start=TemporalBound.unbounded(), + end=TemporalBound.exclusive(datetime.fromisoformat("2021-01-01T00:00:00+00:00")), +) + +subgraph = client.query_entities( + EntityQueryPath().type_().base_url() == Parameter(COMPANY_URL), + options, +) + +buildings = filter_latest_from_subgraph(subgraph) + +devtools.pprint(buildings) diff --git a/libs/hash-graph-sdk/python/examples/query_company_entity_type.py b/libs/hash-graph-sdk/python/examples/query_company_entity_type.py new file mode 100644 index 0000000..c311b9a --- /dev/null +++ b/libs/hash-graph-sdk/python/examples/query_company_entity_type.py @@ -0,0 +1,31 @@ +from uuid import UUID + +from graph_types import EntityTypeReference +from yarl import URL + +from graph_sdk import TypeAPI +from graph_sdk.utils import async_to_sync, print_schema + +graph = TypeAPI(URL("http://localhost:4000/")) + +reference = EntityTypeReference( + **{"$ref": "https://blockprotocol.org/@examples/types/entity-type/company/v/1"}, +) + +entity_type = async_to_sync( + reference.create_model( + actor_id=UUID(int=0), # replace with your actor ID + graph=graph, + additional_properties=False, + ), +) + +print_schema( + entity_type, + { + "https://blockprotocol.org/@examples/types/property-type/e-mail/": None, + "https://blockprotocol.org/@blockprotocol/types/property-type/name/": ( + "Hello World" + ), + }, +) diff --git a/libs/hash-graph-sdk/python/graph_sdk/__init__.py b/libs/hash-graph-sdk/python/graph_sdk/__init__.py new file mode 100644 index 0000000..4e1ab0f --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/__init__.py @@ -0,0 +1,20 @@ +"""Graph API SDK. + +Even though this is a software development kit for the Graph API, +the graph API is still considered to be an implementation detail (for now), +and no guarantees are made about the stability of the API. +""" + +from graph_sdk.client.concurrent import HASHClient +from graph_sdk.types import TypeAPI + +__all__ = [ + "HASHClient", + "TypeAPI", + "client", + "filter", + "options", + "query", + "types", + "utils", +] diff --git a/libs/hash-graph-sdk/python/graph_sdk/client/__init__.py b/libs/hash-graph-sdk/python/graph_sdk/client/__init__.py new file mode 100644 index 0000000..3bc1651 --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/client/__init__.py @@ -0,0 +1 @@ +"""Clients for interacting with the Graph API.""" diff --git a/libs/hash-graph-sdk/python/graph_sdk/client/_compat.py b/libs/hash-graph-sdk/python/graph_sdk/client/_compat.py new file mode 100644 index 0000000..a33045d --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/client/_compat.py @@ -0,0 +1,10 @@ +from typing import TypeVar + +from pydantic import BaseModel + +T = TypeVar("T", bound=BaseModel) +U = TypeVar("U", bound=BaseModel) + + +def recast(type_: type[T], value: U) -> T: + return type_.model_validate(value.model_dump(by_alias=True)) diff --git a/libs/hash-graph-sdk/python/graph_sdk/client/blocking.py b/libs/hash-graph-sdk/python/graph_sdk/client/blocking.py new file mode 100644 index 0000000..dce75f5 --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/client/blocking.py @@ -0,0 +1,99 @@ + +# ========================================= +# THIS FILE IS GENERATED, DO NOT CHANGE IT! +# ========================================= + +"""Blocking API for the Graph SDK. + +This is just a thin wrapper around the async API. + +(Usually, one could achieve this by simply wrapping the async API automatically, +the problem with that approach however is that users loose the ability to look +at the source code) +""" +from graph_sdk.client.concurrent import HASHClient as ConcurrentHASHClient +from graph_sdk.utils import async_to_sync +from typing import TypeVar +from uuid import UUID +from graph_client import GraphClient as LowLevelClient +from graph_client.models import CreateDataTypeRequest, CreateEntityTypeRequest, CreatePropertyTypeRequest, DataType, DataTypeStructuralQuery, EntityStructuralQuery, EntityType, EntityTypeStructuralQuery, LoadExternalDataTypeRequest, LoadExternalEntityTypeRequest, LoadExternalPropertyTypeRequest, MaybeListOfOntologyElementMetadata, OntologyElementMetadata, OwnedById, PropertyType, PropertyTypeStructuralQuery, Subgraph, UpdateDataType, UpdateDataTypeRequest, UpdateEntityType, UpdateEntityTypeRequest, UpdatePropertyType, UpdatePropertyTypeRequest, VersionedURL +from graph_types import DataTypeSchema, EntityTypeSchema, PropertyTypeSchema +from pydantic_core._pydantic_core import Url +from yarl import URL +from graph_sdk.client._compat import recast +from graph_sdk.options import Options +from graph_sdk.query import BaseFilter +T = TypeVar('T') + +class HASHClient: + """Implementation of the client for the HASH API. + + Exposes several methods for interacting with the API. + """ + inner: ConcurrentHASHClient + + def __init__(self, base: URL, *, actor: UUID | None=None) -> None: + """Initialize the client with the base URL.""" + self.inner = ConcurrentHASHClient(base) + + @property + def actor(self) -> UUID | None: + """Get the actor for the client.""" + return self.inner.actor + + @actor.setter + def actor(self, actor: UUID | None) -> None: + """Set the actor for the client.""" + self.inner.actor = actor + + def query_data_types(self, query: BaseFilter, options: Options, *, actor: UUID | None=None) -> Subgraph: + """Query data types.""" + return async_to_sync(self.inner.query_data_types(query, options, actor=actor)) + + def load_external_data_type(self, url: URL, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Load an external data type.""" + return async_to_sync(self.inner.load_external_data_type(url, actor=actor)) + + def create_data_types(self, models: list[DataTypeSchema], owned_by_id: UUID, *, actor: UUID | None=None) -> MaybeListOfOntologyElementMetadata: + """Create data types.""" + return async_to_sync(self.inner.create_data_types(models, owned_by_id, actor=actor)) + + def update_data_type(self, model: DataTypeSchema, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Update a data type.""" + return async_to_sync(self.inner.update_data_type(model, actor=actor)) + + def query_property_types(self, query: BaseFilter, options: Options, *, actor: UUID | None=None) -> Subgraph: + """Query property types.""" + return async_to_sync(self.inner.query_property_types(query, options, actor=actor)) + + def load_external_property_type(self, url: URL, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Load an external property type.""" + return async_to_sync(self.inner.load_external_property_type(url, actor=actor)) + + def create_property_types(self, models: list[PropertyTypeSchema], owned_by_id: UUID, *, actor: UUID | None=None) -> MaybeListOfOntologyElementMetadata: + """Create property types.""" + return async_to_sync(self.inner.create_property_types(models, owned_by_id, actor=actor)) + + def update_property_type(self, model: PropertyTypeSchema, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Update a property type.""" + return async_to_sync(self.inner.update_property_type(model, actor=actor)) + + def query_entity_types(self, query: BaseFilter, options: Options, *, actor: UUID | None=None) -> Subgraph: + """Query entity types.""" + return async_to_sync(self.inner.query_entity_types(query, options, actor=actor)) + + def load_external_entity_type(self, url: URL, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Load an external entity type.""" + return async_to_sync(self.inner.load_external_entity_type(url, actor=actor)) + + def create_entity_types(self, models: list[EntityTypeSchema], owned_by_id: UUID, *, actor: UUID | None=None) -> MaybeListOfOntologyElementMetadata: + """Create entity types.""" + return async_to_sync(self.inner.create_entity_types(models, owned_by_id, actor=actor)) + + def update_entity_type(self, model: EntityTypeSchema, *, actor: UUID | None=None) -> OntologyElementMetadata: + """Update an entity type.""" + return async_to_sync(self.inner.update_entity_type(model, actor=actor)) + + def query_entities(self, query: BaseFilter, options: Options, *, actor: UUID | None=None) -> Subgraph: + """Query entities.""" + return async_to_sync(self.inner.query_entities(query, options, actor=actor)) \ No newline at end of file diff --git a/libs/hash-graph-sdk/python/graph_sdk/client/concurrent.py b/libs/hash-graph-sdk/python/graph_sdk/client/concurrent.py new file mode 100644 index 0000000..d1b00f0 --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/client/concurrent.py @@ -0,0 +1,266 @@ +"""Concurrent (async) client for the HASH API.""" + +from typing import TypeVar +from uuid import UUID + +from graph_client import GraphClient as LowLevelClient +from graph_client.models import ( + CreateDataTypeRequest, + CreateEntityTypeRequest, + CreatePropertyTypeRequest, + DataType, + DataTypeStructuralQuery, + EntityStructuralQuery, + EntityType, + EntityTypeStructuralQuery, + LoadExternalDataTypeRequest, + LoadExternalEntityTypeRequest, + LoadExternalPropertyTypeRequest, + MaybeListOfOntologyElementMetadata, + OntologyElementMetadata, + OwnedById, + PropertyType, + PropertyTypeStructuralQuery, + Subgraph, + UpdateDataType, + UpdateDataTypeRequest, + UpdateEntityType, + UpdateEntityTypeRequest, + UpdatePropertyType, + UpdatePropertyTypeRequest, + VersionedURL, +) +from graph_types import DataTypeSchema, EntityTypeSchema, PropertyTypeSchema +from pydantic_core._pydantic_core import Url +from yarl import URL + +from graph_sdk.client._compat import recast +from graph_sdk.options import Options +from graph_sdk.query import BaseFilter + +T = TypeVar("T") + + +def assert_not_none(value: T | None) -> T: + """Assert that the value is not None.""" + if value is None: + msg = "value cannot be None" + raise ValueError(msg) + + return value + + +# TODO: H-351: Use hash_graph_client for create_entity +# https://linear.app/hash/issue/H-351 +class HASHClient: + """Implementation of the client for the HASH API. + + Exposes several methods for interacting with the API. + """ + + inner: LowLevelClient + + def __init__(self, base: URL, *, actor: UUID | None = None) -> None: + """Initialize the client with the base URL.""" + self.inner = LowLevelClient(base, actor=actor) + self.actor = None + + @property + def actor(self) -> UUID | None: + """Get the actor for the client.""" + return self.inner.actor + + @actor.setter + def actor(self, actor: UUID | None) -> None: + """Set the actor for the client.""" + self.inner.actor = actor + + async def query_data_types( + self, + query: BaseFilter, + options: Options, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query data types.""" + request = DataTypeStructuralQuery( + filter=query.to_ffi(), + graph_resolve_depths=options.graph_resolve_depth, + temporal_axes=options.temporal_axes, + ) + + return await self.inner.query_data_types(request, actor=actor) + + async def load_external_data_type( + self, + url: URL, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external data type.""" + request = LoadExternalDataTypeRequest( + data_type_id=VersionedURL(root=Url(str(url))), + ) + + return await self.inner.load_external_data_type(request, actor=actor) + + async def create_data_types( + self, + models: list[DataTypeSchema], + owned_by_id: UUID, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create data types.""" + request = CreateDataTypeRequest( + owned_by_id=OwnedById(root=owned_by_id), + schema_=[recast(DataType, model) for model in models], + ) + + return await self.inner.create_data_types(request, actor=actor) + + async def update_data_type( + self, + model: DataTypeSchema, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update a data type.""" + request = UpdateDataTypeRequest( + schema_=recast(UpdateDataType, model), + type_to_update=VersionedURL(root=Url(model.identifier)), + ) + + return await self.inner.update_data_type(request, actor=actor) + + async def query_property_types( + self, + query: BaseFilter, + options: Options, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query property types.""" + request = PropertyTypeStructuralQuery( + filter=query.to_ffi(), + graph_resolve_depths=options.graph_resolve_depth, + temporal_axes=options.temporal_axes, + ) + + return await self.inner.query_property_types(request, actor=actor) + + async def load_external_property_type( + self, + url: URL, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external property type.""" + request = LoadExternalPropertyTypeRequest( + property_type_id=VersionedURL(root=Url(str(url))), + ) + + return await self.inner.load_external_property_type(request, actor=actor) + + async def create_property_types( + self, + models: list[PropertyTypeSchema], + owned_by_id: UUID, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create property types.""" + request = CreatePropertyTypeRequest( + owned_by_id=OwnedById(root=owned_by_id), + schema_=[recast(PropertyType, model) for model in models], + ) + + return await self.inner.create_property_types(request, actor=actor) + + async def update_property_type( + self, + model: PropertyTypeSchema, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update a property type.""" + request = UpdatePropertyTypeRequest( + schema_=recast(UpdatePropertyType, model), + type_to_update=VersionedURL(root=Url(model.identifier)), + ) + + return await self.inner.update_property_type(request, actor=actor) + + async def query_entity_types( + self, + query: BaseFilter, + options: Options, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query entity types.""" + request = EntityTypeStructuralQuery( + filter=query.to_ffi(), + graph_resolve_depths=options.graph_resolve_depth, + temporal_axes=options.temporal_axes, + ) + + return await self.inner.query_entity_types(request, actor=actor) + + async def load_external_entity_type( + self, + url: URL, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Load an external entity type.""" + request = LoadExternalEntityTypeRequest( + entity_type_id=VersionedURL(root=Url(str(url))), + ) + + return await self.inner.load_external_entity_type(request, actor=actor) + + async def create_entity_types( + self, + models: list[EntityTypeSchema], + owned_by_id: UUID, + *, + actor: UUID | None = None, + ) -> MaybeListOfOntologyElementMetadata: + """Create entity types.""" + request = CreateEntityTypeRequest( + owned_by_id=OwnedById(root=owned_by_id), + schema_=[recast(EntityType, model) for model in models], + ) + + return await self.inner.create_entity_types(request, actor=actor) + + async def update_entity_type( + self, + model: EntityTypeSchema, + *, + actor: UUID | None = None, + ) -> OntologyElementMetadata: + """Update an entity type.""" + request = UpdateEntityTypeRequest( + schema_=recast(UpdateEntityType, model), + type_to_update=VersionedURL(root=Url(model.identifier)), + ) + + return await self.inner.update_entity_type(request, actor=actor) + + async def query_entities( + self, + query: BaseFilter, + options: Options, + *, + actor: UUID | None = None, + ) -> Subgraph: + """Query entities.""" + request = EntityStructuralQuery( + filter=query.to_ffi(), + graph_resolve_depths=options.graph_resolve_depth, + temporal_axes=options.temporal_axes, + ) + + return await self.inner.query_entities(request, actor=actor) diff --git a/libs/hash-graph-sdk/python/graph_sdk/filter/__init__.py b/libs/hash-graph-sdk/python/graph_sdk/filter/__init__.py new file mode 100644 index 0000000..0e93d8a --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/filter/__init__.py @@ -0,0 +1,20 @@ +"""Ergonomic and type-safe filter paths. + +To start using this module, choose where you need to "start", +depending on the query this will be either: `DataTypeQueryPath`, +`PropertyTypeQueryPath`, `EntityTypeQueryPath`, or `EntityQueryPath`. +""" + +from graph_sdk.filter.path import ( + DataTypeQueryPath, + EntityQueryPath, + EntityTypeQueryPath, + PropertyTypeQueryPath, +) + +__all__ = [ + "EntityQueryPath", + "EntityTypeQueryPath", + "PropertyTypeQueryPath", + "DataTypeQueryPath", +] diff --git a/libs/hash-graph-sdk/python/graph_sdk/filter/base.py b/libs/hash-graph-sdk/python/graph_sdk/filter/base.py new file mode 100644 index 0000000..c798792 --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/filter/base.py @@ -0,0 +1,67 @@ +"""Base and generic classes for query paths.""" + +from abc import ABC +from typing import Generic, Self, TypeVar + +from graph_client import QueryToken +from graph_client.models import Selector + +from graph_sdk.query import Path + + +class AbstractQueryPath(ABC): + """Path definition shared across different query paths.""" + + path: Path + + def __init__(self) -> None: + """Create a new empty path.""" + self.path = Path() + + @classmethod + def from_ffi(cls, value: list[QueryToken]) -> Self: + """Initialize the path from it's vector representation.""" + self = cls() + self.path = Path.from_ffi(value) + return self + + @classmethod + def from_path(cls, path: Path) -> Self: + """Initialize this path from a query path object.""" + self = cls() + self.path = path + return self + + +T = TypeVar("T", bound=AbstractQueryPath) + + +class SelectorQueryPath(AbstractQueryPath, Generic[T]): + """A selector is a path that is used to select a value in an array.""" + + cls: type[T] + + def set_cls(self, cls: type[T]) -> Self: + """Set the class of the selector.""" + self.cls = cls + return self + + def any_(self) -> T: + """Return the path to all values in an array.""" + return self.cls.from_path(self.path.push(Selector(root="*"))) + + +class UntypedQueryPath(AbstractQueryPath): + """Navigation through objects, which is largely untyped.""" + + def array(self, index: int) -> Self: + """Return the path to the array for a property.""" + return self.from_path(self.path.push(index)) + + def key(self, key: str) -> Self: + """Return the path to the key for a property.""" + return self.from_path(self.path.push(key)) + + def finish(self) -> Path: + """Return the path to the finish for a property.""" + return self.path diff --git a/libs/hash-graph-sdk/python/graph_sdk/filter/config.json b/libs/hash-graph-sdk/python/graph_sdk/filter/config.json new file mode 100644 index 0000000..b2d3b4b --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/filter/config.json @@ -0,0 +1,51 @@ +{ + "meta": { + "arguments": { + "inheritanceDepth": { + "type": "uint", + "required": false + } + } + }, + "data_type": { + "selector": {}, + "untyped": [], + "direct": {}, + "arguments": {} + }, + "property_type": { + "selector": { + "data_types": "data_type", + "property_types": "property_type" + }, + "untyped": [], + "direct": {}, + "arguments": {} + }, + "entity_type": { + "selector": { + "properties": "property_type", + "links": "entity_type" + }, + "untyped": [], + "direct": {}, + "arguments": { + "type": ["inheritanceDepth"], + "children": ["inheritanceDepth"] + } + }, + "entity": { + "selector": {}, + "untyped": ["properties"], + "direct": { + "type": "entity_type", + "incoming_links": "entity", + "outgoing_links": "entity", + "left_entity": "entity", + "right_entity": "entity" + }, + "arguments": { + "type": ["inheritanceDepth"] + } + } +} diff --git a/libs/hash-graph-sdk/python/graph_sdk/filter/path.py b/libs/hash-graph-sdk/python/graph_sdk/filter/path.py new file mode 100644 index 0000000..a12ada7 --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/filter/path.py @@ -0,0 +1,226 @@ + +# ========================================= +# THIS FILE IS GENERATED, DO NOT CHANGE IT! +# ========================================= + +"""Definitions for all path objects. + +This file is auto-generated. Do not edit!""" +from typing import Self +from graph_client.models import DataTypeQueryToken, PropertyTypeQueryToken, EntityTypeQueryToken, EntityQueryToken +from graph_sdk.filter.base import AbstractQueryPath, UntypedQueryPath, SelectorQueryPath +from graph_sdk.query import Path + +class DataTypeQueryPath(AbstractQueryPath): + """A query path for a data type.""" + + def base_url(self) -> Path: + """Return the path to the base_url attribute of a data type.""" + return self.path.push(DataTypeQueryToken.base_url) + + def version(self) -> Path: + """Return the path to the version attribute of a data type.""" + return self.path.push(DataTypeQueryToken.version) + + def versioned_url(self) -> Path: + """Return the path to the versioned_url attribute of a data type.""" + return self.path.push(DataTypeQueryToken.versioned_url) + + def owned_by_id(self) -> Path: + """Return the path to the owned_by_id attribute of a data type.""" + return self.path.push(DataTypeQueryToken.owned_by_id) + + def record_created_by_id(self) -> Path: + """Return the path to the record_created_by_id attribute of a data type.""" + return self.path.push(DataTypeQueryToken.record_created_by_id) + + def record_archived_by_id(self) -> Path: + """Return the path to the record_archived_by_id attribute of a data type.""" + return self.path.push(DataTypeQueryToken.record_archived_by_id) + + def title(self) -> Path: + """Return the path to the title attribute of a data type.""" + return self.path.push(DataTypeQueryToken.title) + + def description(self) -> Path: + """Return the path to the description attribute of a data type.""" + return self.path.push(DataTypeQueryToken.description) + + def type_(self) -> Path: + """Return the path to the type attribute of a data type.""" + return self.path.push(DataTypeQueryToken.type) + +class PropertyTypeQueryPath(AbstractQueryPath): + """A query path for a property type.""" + + def base_url(self) -> Path: + """Return the path to the base_url attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.base_url) + + def version(self) -> Path: + """Return the path to the version attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.version) + + def versioned_url(self) -> Path: + """Return the path to the versioned_url attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.versioned_url) + + def owned_by_id(self) -> Path: + """Return the path to the owned_by_id attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.owned_by_id) + + def record_created_by_id(self) -> Path: + """Return the path to the record_created_by_id attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.record_created_by_id) + + def record_archived_by_id(self) -> Path: + """Return the path to the record_archived_by_id attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.record_archived_by_id) + + def title(self) -> Path: + """Return the path to the title attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.title) + + def description(self) -> Path: + """Return the path to the description attribute of a property type.""" + return self.path.push(PropertyTypeQueryToken.description) + + def data_types(self) -> SelectorQueryPath[DataTypeQueryPath]: + """Return the path to the data_types attribute of a property type.""" + return SelectorQueryPath[DataTypeQueryPath].from_path(self.path.push(PropertyTypeQueryToken.data_types)).set_cls(DataTypeQueryPath) + + def property_types(self) -> SelectorQueryPath[Self]: + """Return the path to the property_types attribute of a property type.""" + return SelectorQueryPath[Self].from_path(self.path.push(PropertyTypeQueryToken.property_types)).set_cls(type(self)) + +class EntityTypeQueryPath(AbstractQueryPath): + """A query path for an entity type.""" + + def base_url(self) -> Path: + """Return the path to the base_url attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.base_url) + + def version(self) -> Path: + """Return the path to the version attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.version) + + def versioned_url(self) -> Path: + """Return the path to the versioned_url attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.versioned_url) + + def owned_by_id(self) -> Path: + """Return the path to the owned_by_id attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.owned_by_id) + + def record_created_by_id(self) -> Path: + """Return the path to the record_created_by_id attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.record_created_by_id) + + def record_archived_by_id(self) -> Path: + """Return the path to the record_archived_by_id attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.record_archived_by_id) + + def title(self) -> Path: + """Return the path to the title attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.title) + + def description(self) -> Path: + """Return the path to the description attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.description) + + def examples(self) -> Path: + """Return the path to the examples attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.examples) + + def properties(self) -> SelectorQueryPath[PropertyTypeQueryPath]: + """Return the path to the properties attribute of an entity type.""" + return SelectorQueryPath[PropertyTypeQueryPath].from_path(self.path.push(EntityTypeQueryToken.properties)).set_cls(PropertyTypeQueryPath) + + def required(self) -> Path: + """Return the path to the required attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.required) + + def label_property(self) -> Path: + """Return the path to the label_property attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.label_property) + + def icon(self) -> Path: + """Return the path to the icon attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.icon) + + def links(self) -> SelectorQueryPath[Self]: + """Return the path to the links attribute of an entity type.""" + return SelectorQueryPath[Self].from_path(self.path.push(EntityTypeQueryToken.links)).set_cls(type(self)) + + def inherits_from(self) -> Path: + """Return the path to the inherits_from attribute of an entity type.""" + return self.path.push(EntityTypeQueryToken.inherits_from) + + def children(self, *, inheritance_depth: int | None=None) -> Path: + """Return the path to the children attribute of an entity type.""" + args = [] + if inheritance_depth is not None: + args.append(f'inheritanceDepth={inheritance_depth}') + return self.path.push(f"{EntityTypeQueryToken.children}({', '.join(args)})" if args else EntityTypeQueryToken.children) + +class EntityQueryPath(AbstractQueryPath): + """A query path for an entity.""" + + def uuid(self) -> Path: + """Return the path to the uuid attribute of an entity.""" + return self.path.push(EntityQueryToken.uuid) + + def edition_id(self) -> Path: + """Return the path to the edition_id attribute of an entity.""" + return self.path.push(EntityQueryToken.edition_id) + + def archived(self) -> Path: + """Return the path to the archived attribute of an entity.""" + return self.path.push(EntityQueryToken.archived) + + def draft(self) -> Path: + """Return the path to the draft attribute of an entity.""" + return self.path.push(EntityQueryToken.draft) + + def owned_by_id(self) -> Path: + """Return the path to the owned_by_id attribute of an entity.""" + return self.path.push(EntityQueryToken.owned_by_id) + + def record_created_by_id(self) -> Path: + """Return the path to the record_created_by_id attribute of an entity.""" + return self.path.push(EntityQueryToken.record_created_by_id) + + def type_(self, *, inheritance_depth: int | None=None) -> EntityTypeQueryPath: + """Return the path to the type attribute of an entity.""" + args = [] + if inheritance_depth is not None: + args.append(f'inheritanceDepth={inheritance_depth}') + return EntityTypeQueryPath.from_path(self.path.push(f"{EntityQueryToken.type}({', '.join(args)})" if args else EntityQueryToken.type)) + + def properties(self) -> UntypedQueryPath: + """Return the path to the properties attribute of an entity.""" + return UntypedQueryPath.from_path(self.path.push(EntityQueryToken.properties)) + + def incoming_links(self) -> Self: + """Return the path to the incoming_links attribute of an entity.""" + return self.from_path(self.path.push(EntityQueryToken.incoming_links)) + + def outgoing_links(self) -> Self: + """Return the path to the outgoing_links attribute of an entity.""" + return self.from_path(self.path.push(EntityQueryToken.outgoing_links)) + + def left_entity(self) -> Self: + """Return the path to the left_entity attribute of an entity.""" + return self.from_path(self.path.push(EntityQueryToken.left_entity)) + + def right_entity(self) -> Self: + """Return the path to the right_entity attribute of an entity.""" + return self.from_path(self.path.push(EntityQueryToken.right_entity)) + + def left_to_right_order(self) -> Path: + """Return the path to the left_to_right_order attribute of an entity.""" + return self.path.push(EntityQueryToken.left_to_right_order) + + def right_to_left_order(self) -> Path: + """Return the path to the right_to_left_order attribute of an entity.""" + return self.path.push(EntityQueryToken.right_to_left_order) \ No newline at end of file diff --git a/libs/hash-graph-sdk/python/graph_sdk/options.py b/libs/hash-graph-sdk/python/graph_sdk/options.py new file mode 100644 index 0000000..d1736ea --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/options.py @@ -0,0 +1,372 @@ +"""Ergonomic API to configure options for structural queries.""" + +from datetime import datetime +from typing import Protocol + +from graph_client.models import ( + DecisionTime, + EdgeResolveDepths, + ExclusiveBound, + GraphResolveDepths, + InclusiveBound, + LimitedTemporalBound, + NullableTimestamp, + OpenTemporalBound, + OutgoingEdgeResolveDepth, + QueryTemporalAxesUnresolved, + QueryTemporalAxesUnresolvedDecisionTime, + QueryTemporalAxesUnresolvedTransactionTime, + Timestamp, + TransactionTime, + UnboundedBound, + UnresolvedPinnedDecisionAxis, + UnresolvedPinnedTransactionAxis, + UnresolvedRightBoundedTemporalInterval, + UnresolvedVariableDecisionAxis, + UnresolvedVariableTransactionAxis, +) +from graph_client.models import ( + TemporalBound as FFITemporalBound, +) + + +class ToLimitedTemporalBound(Protocol): + """Convert to a limited temporal bound. + + This is implemented by `InclusiveTemporalBound`, and `ExclusiveTemporalBound`. + """ + + def to_limited_temporal_bound(self) -> LimitedTemporalBound: + """Convert to a limited temporal bound.""" + ... + + +class ToTemporalBound(Protocol): + """Convert to a temporal bound. + + This is implemented by `UnboundedTemporalBound`, + `InclusiveTemporalBound` and `ExclusiveTemporalBound`. + """ + + def to_temporal_bound(self) -> FFITemporalBound: + """Convert to a temporal bound.""" + ... + + +class ToOpenTemporalBound(Protocol): + """Convert to an open temporal bound. + + This is implemented by `UnboundedTemporalBound` and `ExclusiveTemporalBound`. + """ + + def to_open_temporal_bound(self) -> OpenTemporalBound: + """Convert to an open temporal bound.""" + ... + + +class TemporalBound: + """A temporal bound. + + Do not instantiate this class directly. + Instead, use the class methods. + """ + + @classmethod + def unbounded(cls) -> "UnboundedTemporalBound": + """Return an unbounded interval.""" + return UnboundedTemporalBound() + + @classmethod + def inclusive(cls, time: datetime) -> "InclusiveTemporalBound": + """Return an inclusive interval.""" + return InclusiveTemporalBound(time) + + @classmethod + def exclusive(cls, time: datetime) -> "ExclusiveTemporalBound": + """Return an exclusive interval.""" + return ExclusiveTemporalBound(time) + + +# noinspection PyMethodMayBeStatic +class UnboundedTemporalBound(TemporalBound): + """An unbounded temporal bound.""" + + def to_temporal_bound(self) -> FFITemporalBound: + """Convert to a temporal bound.""" + return FFITemporalBound(root=UnboundedBound(kind="unbounded")) + + def to_open_temporal_bound(self) -> OpenTemporalBound: + """Convert to an open temporal bound.""" + return OpenTemporalBound(root=UnboundedBound(kind="unbounded")) + + +class InclusiveTemporalBound(TemporalBound): + """An inclusive temporal bound.""" + + time: datetime + + def __init__(self, time: datetime) -> None: + """Initialize the bound.""" + self.time = time + + def to_temporal_bound(self) -> FFITemporalBound: + """Convert to a temporal bound.""" + return FFITemporalBound( + root=InclusiveBound( + kind="inclusive", + limit=Timestamp(root=self.time), + ), + ) + + def to_limited_temporal_bound(self) -> LimitedTemporalBound: + """Convert to a limited temporal bound.""" + return LimitedTemporalBound( + root=InclusiveBound( + kind="inclusive", + limit=Timestamp(root=self.time), + ), + ) + + +class ExclusiveTemporalBound(TemporalBound): + """An exclusive temporal bound.""" + + time: datetime + + def __init__(self, time: datetime) -> None: + """Initialize the bound.""" + self.time = time + + def to_temporal_bound(self) -> FFITemporalBound: + """Convert to a temporal bound.""" + return FFITemporalBound( + root=ExclusiveBound(kind="exclusive", limit=Timestamp(root=self.time)), + ) + + def to_limited_temporal_bound(self) -> LimitedTemporalBound: + """Convert to a limited temporal bound.""" + return LimitedTemporalBound( + root=ExclusiveBound( + kind="exclusive", + limit=Timestamp(root=self.time), + ), + ) + + def to_open_temporal_bound(self) -> OpenTemporalBound: + """Convert to an open temporal bound.""" + return OpenTemporalBound( + root=ExclusiveBound( + kind="exclusive", + limit=Timestamp(root=self.time), + ), + ) + + +class PinnedTransactionTimeTemporalAxisBuilder: + """A builder for a pinned transaction time, which is variable by decision time.""" + + pinned: datetime | None = None + + def __init__(self, *, pinned: datetime | None = None) -> None: + """Initialize the builder.""" + self.pinned = pinned + + def between( + self, + *, + start: ToTemporalBound | None = None, + end: ToLimitedTemporalBound | None = None, + ) -> QueryTemporalAxesUnresolved: + """Return all entities that are valid between the given times. + + If `start` is None, then the start of the interval is unbounded. + If `end` is None, then the end will be the current time. + """ + return QueryTemporalAxesUnresolved( + root=QueryTemporalAxesUnresolvedDecisionTime( + pinned=UnresolvedPinnedTransactionAxis( + axis=TransactionTime(root="transactionTime"), + timestamp=NullableTimestamp(root=self.pinned), + ), + variable=UnresolvedVariableDecisionAxis( + axis=DecisionTime(root="decisionTime"), + interval=UnresolvedRightBoundedTemporalInterval( + start=start.to_temporal_bound() if start else None, + end=end.to_limited_temporal_bound() if end else None, + ), + ), + ), + ) + + def current(self) -> QueryTemporalAxesUnresolved: + """Return all entities that are valid at the current time.""" + return self.between(start=None, end=None) + + +class PinnedDecisionTimeTemporalAxisBuilder: + """A builder for a pinned decision time, which is variable by transaction time.""" + + pinned: datetime | None = None + + def __init__(self, *, pinned: datetime | None = None) -> None: + """Initialize the builder.""" + self.pinned = pinned + + def between( + self, + *, + start: ToTemporalBound | None = None, + end: ToLimitedTemporalBound | None = None, + ) -> QueryTemporalAxesUnresolved: + """Return all entities that are valid between the given times. + + If `start` is None, then the start of the interval is unbounded. + If `end` is None, then the end will be the current time. + """ + return QueryTemporalAxesUnresolved( + root=QueryTemporalAxesUnresolvedTransactionTime( + pinned=UnresolvedPinnedDecisionAxis( + axis=DecisionTime(root="decisionTime"), + timestamp=NullableTimestamp(root=self.pinned), + ), + variable=UnresolvedVariableTransactionAxis( + axis=TransactionTime(root="transactionTime"), + interval=UnresolvedRightBoundedTemporalInterval( + start=start.to_temporal_bound() if start else None, + end=end.to_limited_temporal_bound() if end else None, + ), + ), + ), + ) + + def current(self) -> QueryTemporalAxesUnresolved: + """Return all entities that are valid at the current time.""" + return self.between(start=None, end=None) + + +class TemporalAxesBuilder: + """A builder for temporal axes.""" + + @classmethod + def pinned_transaction_time( + cls, + time: datetime | None = None, + ) -> PinnedTransactionTimeTemporalAxisBuilder: + """Return all entities that are available at the given transaction time.""" + return PinnedTransactionTimeTemporalAxisBuilder(pinned=time) + + @classmethod + def pinned_decision_time( + cls, + time: datetime | None = None, + ) -> PinnedDecisionTimeTemporalAxisBuilder: + """Return all entities that are available at the given transaction time.""" + return PinnedDecisionTimeTemporalAxisBuilder(pinned=time) + + @classmethod + def current(cls) -> QueryTemporalAxesUnresolved: + """Only select the latest entities.""" + return PinnedDecisionTimeTemporalAxisBuilder(pinned=None).current() + + +class Options: + """Options for queries.""" + + graph_resolve_depth: GraphResolveDepths + temporal_axes: QueryTemporalAxesUnresolved + + def __init__(self) -> None: + """Initialize the options.""" + self.graph_resolve_depth = GraphResolveDepths( + constrains_link_destinations_on=OutgoingEdgeResolveDepth(outgoing=0), + constrains_links_on=OutgoingEdgeResolveDepth(outgoing=0), + constrains_properties_on=OutgoingEdgeResolveDepth(outgoing=0), + constrains_values_on=OutgoingEdgeResolveDepth(outgoing=0), + has_left_entity=EdgeResolveDepths(incoming=0, outgoing=0), + has_right_entity=EdgeResolveDepths(incoming=0, outgoing=0), + inherits_from=OutgoingEdgeResolveDepth(outgoing=0), + is_of_type=OutgoingEdgeResolveDepth(outgoing=0), + ) + + self.temporal_axes = TemporalAxesBuilder.current() + + def resolve_type_of_entity(self, *, enable: bool) -> None: + """Return the entity type of the entity.""" + self.graph_resolve_depth.is_of_type = OutgoingEdgeResolveDepth( + outgoing=0 if enable else 1, + ) + + def resolve_inheritance(self, *, depth: int) -> None: + """Return the types a type inherits from. + + If `depth` is 0, then types an entity inherits from will not be resolved. + """ + self.graph_resolve_depth.inherits_from = OutgoingEdgeResolveDepth( + outgoing=depth, + ) + + def resolve_left_entity_of_link( + self, + *, + incoming_depth: int = 0, + outgoing_depth: int = 0, + ) -> None: + """Return the left entity of an entity, if it is a link. + + If `*_depth` is 0, then the right entity will not be resolved. + """ + self.graph_resolve_depth.has_left_entity = EdgeResolveDepths( + incoming=incoming_depth, + outgoing=outgoing_depth, + ) + + def resolve_right_entity_of_link( + self, + *, + incoming_depth: int = 0, + outgoing_depth: int = 0, + ) -> None: + """Return the right entity of an entity, if it is a link. + + If `*_depth` is 0, then the right entity will not be resolved. + """ + self.graph_resolve_depth.has_right_entity = EdgeResolveDepths( + incoming=incoming_depth, + outgoing=outgoing_depth, + ) + + def resolve_data_types(self, *, depth: int) -> None: + """Return the data types of the entity. + + If `depth` is 0, then the data types will not be resolved. + """ + self.graph_resolve_depth.constrains_values_on = OutgoingEdgeResolveDepth( + outgoing=depth, + ) + + def resolve_property_types(self, *, depth: int) -> None: + """Return the property types of the entity. + + If `depth` is 0, then the property types will not be resolved. + """ + self.graph_resolve_depth.constrains_properties_on = OutgoingEdgeResolveDepth( + outgoing=depth, + ) + + def resolve_link_types(self, *, depth: int) -> None: + """Return the entity types of any link left or right entity. + + If `depth` is 0, then the link types will not be resolved. + """ + self.graph_resolve_depth.constrains_links_on = OutgoingEdgeResolveDepth( + outgoing=depth, + ) + + def resolve_link_destinations(self, *, depth: int) -> None: + """Return the entity type of any link destination referenced by an entity type. + + If `depth` is 0, then the link destinations will not be resolved. + """ + self.graph_resolve_depth.constrains_link_destinations_on = ( + OutgoingEdgeResolveDepth(outgoing=depth) + ) diff --git a/libs/hash-graph-sdk/python/graph_sdk/py.typed b/libs/hash-graph-sdk/python/graph_sdk/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/libs/hash-graph-sdk/python/graph_sdk/query.py b/libs/hash-graph-sdk/python/graph_sdk/query.py new file mode 100644 index 0000000..e995f0c --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/query.py @@ -0,0 +1,366 @@ +"""Ergonomic API to create different type-checked filters for use in structural queries. + +This module provides a set of classes +that can be used to create type-checked filters for +use in structural queries. + +To combine filters use the `&` and `|` operators. If you prefer explicit operations, +you can also use `BaseFilter.and_()` and `BaseFilter.or_()` respectively. + +To create filters use `==` or `!=` with a `Path` and `Parameter`. +If you prefer explicit operations you can also use `BaseFilter.equal()` +and `BaseFilter.not_equal()` respectively. + +To create a filter that will always match use `BaseFilter.always()`. +Use `BaseFilter.never()` to create a filter that will never match. +""" + +from abc import ABC, abstractmethod +from collections.abc import Sequence +from enum import Enum +from typing import Any, Generic, Never, Protocol, Self, TypeVar, assert_never + +from graph_client import QueryToken +from graph_client.models import ( + AllFilter, + AnyFilter, + ContainsSegmentFilter, + EndsWithFilter, + EqualFilter, + Filter, + FilterExpression, + NotEqualFilter, + NotFilter, + ParameterExpression, + PathExpression, + StartsWithFilter, +) +from pydantic import BaseModel + + +class FFIConversionProtocol(Protocol): + """Protocol for converting to and from FFI objects.""" + + def to_ffi(self) -> BaseModel: + """Converts the object to a FFI object.""" + ... + + +class UnaryOperation(Enum): + """Unary operations.""" + + NOT = "not" + + +class BinaryOperation(Enum): + """Binary operations.""" + + EQUAL = "equal" + NOT_EQUAL = "notEqual" + STARTS_WITH = "startsWith" + ENDS_WITH = "endsWith" + CONTAINS_SEGMENT = "containsSegment" + + +class NaryOperation(Enum): + """Nary operations.""" + + ALL = "all" + ANY = "any" + + +L = TypeVar("L", bound="BaseFilterExpression") +R = TypeVar("R", bound="BaseFilterExpression") +F = TypeVar("F", bound="BaseFilter") + + +class BaseFilter(ABC): + """Protocol for queries.""" + + def all_( + self, + other: Sequence[F], + ) -> "NaryFilter[Self | F]": + """Combines two or more queries with an AND.""" + return NaryFilter(NaryOperation.ALL, [self, *other]) + + def __and__(self, other: F) -> "NaryFilter[Self | F]": + """Combines two queries with an AND.""" + if isinstance(other, BaseFilter): + return self.all_((other,)) + + msg: str # type: ignore[unreachable] + msg = f"unsupported operand type(s) for &: '{type(self)}' and '{type(other)}'" + raise TypeError(msg) + + def any_( + self, + other: Sequence[F], + ) -> "NaryFilter[Self | F]": + """Combines two or more queries with an OR.""" + return NaryFilter(NaryOperation.ANY, [self, *other]) + + def __or__(self, other: F) -> "NaryFilter[Self | F]": + """Combines two queries with an OR.""" + if isinstance(other, BaseFilter): + return self.any_((other,)) + + msg: str # type: ignore[unreachable] + msg = f"unsupported operand type(s) for |: '{type(self)}' and '{type(other)}'" + raise TypeError(msg) + + def not_(self) -> "UnaryFilter[Self]": + """Negates the query.""" + return UnaryFilter(UnaryOperation.NOT, self) + + def __invert__(self) -> "UnaryFilter[Self]": + """Negates the query.""" + return self.not_() + + @classmethod + def always(cls) -> "NaryFilter[Never]": + """Returns a query that always returns true. + + Warning: + ------- + Using this query is generally discouraged, + and should only be used if there is no other way. + + This will return everything, which means that depending + on graph size, this **will** return a lot of data. + """ + return NaryFilter(NaryOperation.ALL, []) + + @classmethod + def never(cls) -> "NaryFilter[Never]": + """Returns a query that always returns false.""" + return NaryFilter(NaryOperation.ANY, []) + + @abstractmethod + def to_ffi(self) -> Filter: + """Converts the query to an FFI query.""" + ... + + +class UnaryFilter(BaseFilter, Generic[F]): + """Unary query.""" + + operation: UnaryOperation + operand: F + + def __init__(self, operation: UnaryOperation, operand: F) -> None: + """Initializes the unary query.""" + self.operation = operation + self.operand = operand + + def __repr__(self) -> str: + """Returns a string representation of the unary query.""" + return f"UnaryFilter({self.operation}, {self.operand})" + + def to_ffi(self) -> Filter: + """Converts the query to an FFI query.""" + operation = self.operation + + if operation == UnaryOperation.NOT: + return Filter(root=NotFilter(not_=self.operand.to_ffi())) + + assert_never(operation) + + +class BinaryFilter(BaseFilter, Generic[L, R]): + """Binary query.""" + + operation: BinaryOperation + lhs: L + rhs: R + + def __init__(self, operation: BinaryOperation, lhs: L, rhs: R) -> None: + """Initializes the binary query.""" + self.operation = operation + self.lhs = lhs + self.rhs = rhs + + def __repr__(self) -> str: + """Returns a string representation of the binary query.""" + return f"BinaryFilter({self.operation}, {self.lhs}, {self.rhs})" + + def to_ffi(self) -> Filter: + """Converts the query to an FFI query.""" + operation = self.operation + + match operation: + case BinaryOperation.EQUAL: + return Filter( + root=EqualFilter( + equal=[self.lhs.to_ffi(), self.rhs.to_ffi()], + ), + ) + case BinaryOperation.NOT_EQUAL: + return Filter( + root=NotEqualFilter( + not_equal=[self.lhs.to_ffi(), self.rhs.to_ffi()], + ), + ) + case BinaryOperation.STARTS_WITH: + return Filter( + root=StartsWithFilter( + starts_with=[self.lhs.to_ffi(), self.rhs.to_ffi()], + ), + ) + case BinaryOperation.ENDS_WITH: + return Filter( + root=EndsWithFilter( + ends_with=[self.lhs.to_ffi(), self.rhs.to_ffi()], + ), + ) + case BinaryOperation.CONTAINS_SEGMENT: + return Filter( + root=ContainsSegmentFilter( + contains_segment=[self.lhs.to_ffi(), self.rhs.to_ffi()], + ), + ) + case _: + assert_never(operation) + + +# I would love to use TypeVarTuple here, but the ecosystem is not ready yet. +class NaryFilter(BaseFilter, Generic[F]): + """Nary query.""" + + operation: NaryOperation + operands: list[F] + + def __init__( + self, + operation: NaryOperation, + operands: Sequence[F], + ) -> None: + """Initializes the nary query.""" + self.operation = operation + self.operands = [*operands] + + def __repr__(self) -> str: + """Returns a string representation of the nary query.""" + return f"NaryFilter({self.operation}, {self.operands})" + + def to_ffi(self) -> Filter: + """Converts the query to an FFI query.""" + operation = self.operation + + match operation: + case NaryOperation.ALL: + return Filter( + root=AllFilter( + all=[operand.to_ffi() for operand in self.operands], + ), + ) + case NaryOperation.ANY: + return Filter( + root=AnyFilter( + any=[operand.to_ffi() for operand in self.operands], + ), + ) + case _: + assert_never(operation) + + +class BaseFilterExpression(ABC): + """Protocol for filters.""" + + def equals(self, other: R) -> BinaryFilter[Self, R]: + """Checks if two filters are equal.""" + return BinaryFilter(BinaryOperation.EQUAL, self, other) + + def __eq__(self, other: R) -> BinaryFilter[Self, R]: # type: ignore[override] + """Checks if two filters are equal.""" + if isinstance(other, BaseFilterExpression): + return self.equals(other) + + msg: str # type: ignore[unreachable] + msg = f"unsupported operand type(s) for ==: '{type(self)}' and '{type(other)}'" + raise TypeError(msg) + + def not_equals(self, other: R) -> BinaryFilter[Self, R]: + """Checks if two filters are not equal.""" + return BinaryFilter(BinaryOperation.NOT_EQUAL, self, other) + + def __ne__(self, other: R) -> BinaryFilter[Self, R]: # type: ignore[override] + """Checks if two filters are not equal.""" + if isinstance(other, BaseFilterExpression): + return self.not_equals(other) + + msg: str # type: ignore[unreachable] + msg = f"unsupported operand type(s) for !=: '{type(self)}' and '{type(other)}'" + raise TypeError(msg) + + def starts_with(self, other: R) -> BinaryFilter[Self, R]: + """Checks if the left filter starts with the right filter.""" + return BinaryFilter(BinaryOperation.STARTS_WITH, self, other) + + def ends_with(self, other: R) -> BinaryFilter[Self, R]: + """Checks if the left filter ends with the right filter.""" + return BinaryFilter(BinaryOperation.ENDS_WITH, self, other) + + def contains_segment(self, other: R) -> BinaryFilter[Self, R]: + """Checks if the left filter contains the right filter as a segment.""" + return BinaryFilter(BinaryOperation.CONTAINS_SEGMENT, self, other) + + @abstractmethod + def to_ffi(self) -> FilterExpression: + """Converts the filter to an FFI filter.""" + ... + + +class Parameter(BaseFilterExpression): + """Values that are given to queries as parameters.""" + + value: Any + + def __init__(self, value: Any) -> None: # noqa: ANN401 + """Initializes the parameter with a value.""" + self.value = value + + def __repr__(self) -> str: + """Returns a string representation of the parameter.""" + return f"Parameter({self.value!r})" + + def to_ffi(self) -> FilterExpression: + """Converts the parameter to a FFI object.""" + return FilterExpression(root=ParameterExpression(parameter=self.value)) + + +class Path(BaseFilterExpression): + """A path to a value in a query.""" + + value: list[QueryToken] + + def __init__(self) -> None: + """Initialize the path with an empty vector.""" + self.value = [] + + def __repr__(self) -> str: + """Return the repr.""" + return f"{self.__class__.__name__}({self.value!r})" + + @classmethod + def from_ffi(cls, value: list[QueryToken]) -> Self: + """Initialize the path with a vector.""" + self = cls() + self.value = value[::] + + return self + + def push(self, value: QueryToken) -> Self: + """Push a value onto the path.""" + tokens = self.value[::] + tokens.append(value) + + return self.from_ffi(tokens) + + def _finish(self) -> PathExpression: + """Finish the path.""" + return PathExpression(path=self.value) + + def to_ffi(self) -> FilterExpression: + """Converts the path to a FFI object.""" + return FilterExpression(root=self._finish()) diff --git a/libs/hash-graph-sdk/python/graph_sdk/types.py b/libs/hash-graph-sdk/python/graph_sdk/types.py new file mode 100644 index 0000000..bf36beb --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/types.py @@ -0,0 +1,212 @@ +"""Create dynamic types from entity, property, and data types via pydantic.""" + +from uuid import UUID + +from graph_types import ( + DataTypeSchema, + EntityTypeSchema, + PropertyTypeSchema, +) +from yarl import URL + +from graph_sdk.client.concurrent import HASHClient +from graph_sdk.filter import ( + DataTypeQueryPath, + EntityTypeQueryPath, + PropertyTypeQueryPath, +) +from graph_sdk.options import Options +from graph_sdk.query import Parameter +from graph_sdk.utils import ( + async_to_sync, + filter_latest_ontology_types_from_subgraph, +) + + +class TypeAPI: + """GraphAPI for use with hash-graph-types.""" + + inner: HASHClient + + def __init__(self, base: URL) -> None: + """Initialize the client with the base URL.""" + self.inner = HASHClient(base) + + async def load_data_type( + self, + data_type_id: str, + *, + actor_id: UUID, + ) -> DataTypeSchema: + """Load an external data type.""" + await self.inner.load_external_data_type(URL(data_type_id), actor=actor_id) + + return await self.get_data_type( + data_type_id, + actor_id=actor_id, + is_after_load=True, + ) + + async def get_data_type( + self, + data_type_id: str, + *, + actor_id: UUID, + is_after_load: bool = False, + ) -> DataTypeSchema: + """Returns the data type schema for the given data type ID. + + If the data type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + TODO: remove this once H-136 is resolved. + """ + subgraph = await self.inner.query_data_types( + DataTypeQueryPath().versioned_url() == Parameter(data_type_id), + Options(), + actor=actor_id, + ) + + latest = filter_latest_ontology_types_from_subgraph(subgraph) + if not latest: + if is_after_load: + msg = f"Could not find data type {data_type_id}" + raise ValueError(msg) + + return await self.load_data_type(data_type_id, actor_id=actor_id) + + vertex = latest[0] + data_type = vertex.root.inner.schema_ + + return DataTypeSchema(**data_type.model_dump(by_alias=True, mode="json")) + + def get_data_type_sync( + self, + data_type_id: str, + *, + actor_id: UUID, + ) -> DataTypeSchema: + """Returns the data type schema for the given data type ID.""" + return async_to_sync(self.get_data_type(data_type_id, actor_id=actor_id)) + + async def load_property_type( + self, + property_type_id: str, + *, + actor_id: UUID, + ) -> PropertyTypeSchema: + """Load an external property type.""" + await self.inner.load_external_property_type( + URL(property_type_id), + actor=actor_id, + ) + + return await self.get_property_type( + property_type_id, + actor_id=actor_id, + is_after_load=True, + ) + + async def get_property_type( + self, + property_type_id: str, + *, + actor_id: UUID, + is_after_load: bool = False, + ) -> PropertyTypeSchema: + """Returns the property type schema for the given property type ID. + + If the property type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + TODO: remove this once H-136 is resolved. + """ + subgraph = await self.inner.query_property_types( + PropertyTypeQueryPath().versioned_url() == Parameter(property_type_id), + Options(), + actor=actor_id, + ) + + latest = filter_latest_ontology_types_from_subgraph(subgraph) + if not latest: + if is_after_load: + msg = f"Could not find property type {property_type_id}" + raise ValueError(msg) + + return await self.load_property_type(property_type_id, actor_id=actor_id) + + vertex = latest[0] + property_type = vertex.root.inner.schema_ + + return PropertyTypeSchema( + **property_type.model_dump(by_alias=True, mode="json"), + ) + + def get_property_type_sync( + self, + property_type_id: str, + *, + actor_id: UUID, + ) -> PropertyTypeSchema: + """Returns the property type schema for the given property type ID.""" + return async_to_sync( + self.get_property_type(property_type_id, actor_id=actor_id), + ) + + async def load_entity_type( + self, + entity_type_id: str, + *, + actor_id: UUID, + ) -> EntityTypeSchema: + """Load an external entity type.""" + await self.inner.load_external_entity_type( + URL(entity_type_id), + actor=actor_id, + ) + + return await self.get_entity_type( + entity_type_id, + actor_id=actor_id, + is_after_load=True, + ) + + async def get_entity_type( + self, + entity_type_id: str, + *, + actor_id: UUID, + is_after_load: bool = False, + ) -> EntityTypeSchema: + """Returns the entity type schema for the given entity type ID. + + If the entity type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + TODO: remove this once H-136 is resolved. + """ + subgraph = await self.inner.query_entity_types( + EntityTypeQueryPath().versioned_url() == Parameter(entity_type_id), + Options(), + actor=actor_id, + ) + + latest = filter_latest_ontology_types_from_subgraph(subgraph) + + if not latest: + if is_after_load: + msg = f"Could not find entity type {entity_type_id}" + raise ValueError(msg) + + return await self.load_entity_type(entity_type_id, actor_id=actor_id) + + vertex = latest[0] + entity_type = vertex.root.inner.schema_ + + return EntityTypeSchema(**entity_type.model_dump(by_alias=True, mode="json")) + + def get_entity_type_sync( + self, + entity_type_id: str, + *, + actor_id: UUID, + ) -> EntityTypeSchema: + """Returns the entity type schema for the given entity type ID.""" + return async_to_sync(self.get_entity_type(entity_type_id, actor_id=actor_id)) diff --git a/libs/hash-graph-sdk/python/graph_sdk/utils.py b/libs/hash-graph-sdk/python/graph_sdk/utils.py new file mode 100644 index 0000000..a9e9cca --- /dev/null +++ b/libs/hash-graph-sdk/python/graph_sdk/utils.py @@ -0,0 +1,92 @@ +"""Miscellaneous utilities for the SDK.""" + +import asyncio +from collections.abc import Awaitable +from typing import TYPE_CHECKING, Any, TypeVar + +from graph_client.models import KnowledgeGraphVertex, OntologyVertex, Subgraph +from pydantic import BaseModel, ValidationError + +if TYPE_CHECKING: + from types import EllipsisType + +try: + # noinspection PyUnresolvedReferences + import devtools + + IS_DEV = True +except ImportError: + IS_DEV = False + +T = TypeVar("T") + +Missing = ... + + +def async_to_sync(awaitable: Awaitable[T]) -> T: + """Run an awaitable and return the result. + + Different from `asyncio.run` in that it does not create a new event loop each time. + """ + response: T | "EllipsisType" = Missing + + async def run_and_capture() -> None: + nonlocal response + response = await awaitable + + loop = asyncio.get_event_loop() + coroutine = run_and_capture() + loop.run_until_complete(coroutine) + + if response is Missing: + msg = "response was not set" + raise ValueError(msg) + + return response + + +def filter_latest_from_subgraph( + subgraph: Subgraph, +) -> list[KnowledgeGraphVertex | OntologyVertex]: + """Filters the latest version of each entity from a subgraph.""" + # is typed wrong, this can never be None + vertices = subgraph.vertices.root or {} + + vertices_versions = (vertex for vertex in vertices.values() if vertex) + sorted_versions = ( + sorted(vertex.items(), key=lambda kv: kv[0], reverse=True) + for vertex in vertices_versions + ) + + latest_vertices = (next(iter(entity)) for entity in sorted_versions) + + return [vertex[1] for vertex in latest_vertices if vertex] + + +def filter_latest_ontology_types_from_subgraph( + subgraph: Subgraph, +) -> list[OntologyVertex]: + """Filters the latest version of each ontology type from a subgraph.""" + return [ + vertex + for vertex in filter_latest_from_subgraph(subgraph) + if isinstance(vertex, OntologyVertex) + ] + + +def print_schema(model: type[BaseModel], data: Any) -> None: # noqa: ANN401 + """Function to print the schema and the value of a BaseModel. + + Debugging purposes only. + """ + if not IS_DEV: + return + + devtools.pprint(model.model_json_schema()) + + try: + parsed_data = model.model_validate(data) + except ValidationError as err: + devtools.pprint(err) + else: + devtools.pprint(parsed_data.model_dump()) diff --git a/libs/hash-graph-sdk/python/package.json b/libs/hash-graph-sdk/python/package.json new file mode 100644 index 0000000..b3b324e --- /dev/null +++ b/libs/hash-graph-sdk/python/package.json @@ -0,0 +1,25 @@ +{ + "name": "@local/hash-graph-sdk-py", + "version": "0.0.0-private", + "private": true, + "description": "Type definitions for the type system and entity validation based on schemas", + "scripts": { + "build": "poetry build --no-interaction", + "codegen:blocking": "poetry run python ./scripts/generate_blocking.py", + "codegen:filter": "poetry run python ./scripts/generate_filter.py", + "fix:black": "poetry run black graph_sdk", + "fix:lock-files": "poetry lock --no-update", + "fix:ruff": "poetry run ruff graph_sdk --fix", + "lint:black": "poetry run black --check --diff --color graph_sdk", + "lint:lock-files": "poetry lock --check", + "lint:mypy": "poetry run mypy .", + "lint:ruff": "poetry run ruff graph_sdk", + "poetry:install": "poetry install --no-root --no-interaction", + "poetry:install-production": "poetry install --no-root --no-interaction --only main" + }, + "dependencies": { + "@local/hash-graph-client-py": "0.0.0-private", + "@local/hash-graph-types-py": "0.0.0-private" + }, + "devDependencies": {} +} diff --git a/libs/hash-graph-sdk/python/poetry.lock b/libs/hash-graph-sdk/python/poetry.lock new file mode 100644 index 0000000..42bd30c --- /dev/null +++ b/libs/hash-graph-sdk/python/poetry.lock @@ -0,0 +1,791 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[[package]] +name = "anyio" +version = "3.7.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + +[[package]] +name = "asttokens" +version = "2.2.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, + {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, +] + +[package.dependencies] +six = "*" + +[package.extras] +test = ["astroid", "pytest"] + +[[package]] +name = "black" +version = "23.10.1" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, + {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, + {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, + {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, + {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, + {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, + {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, + {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, + {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, + {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, + {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "click" +version = "8.1.6" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, + {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "devtools" +version = "0.12.2" +description = "Python's missing debug print command, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "devtools-0.12.2-py3-none-any.whl", hash = "sha256:c366e3de1df4cdd635f1ad8cbcd3af01a384d7abda71900e68d43b04eb6aaca7"}, + {file = "devtools-0.12.2.tar.gz", hash = "sha256:efceab184cb35e3a11fa8e602cc4fadacaa2e859e920fc6f87bf130b69885507"}, +] + +[package.dependencies] +asttokens = ">=2.0.0,<3.0.0" +executing = ">=1.1.1" +pygments = ">=2.15.0" + +[[package]] +name = "executing" +version = "1.2.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = "*" +files = [ + {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, + {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, +] + +[package.extras] +tests = ["asttokens", "littleutils", "pytest", "rich"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "hash-graph-client" +version = "0.0.0" +description = "OpenAPI client for the HASH Graph API" +optional = false +python-versions = "^3.11" +files = [] +develop = true + +[package.dependencies] +httpx = "^0.25.0" +pydantic = "^2.4.2" +yarl = "^1.9.2" + +[package.source] +type = "directory" +url = "../../hash-graph-client/python" + +[[package]] +name = "hash-graph-types" +version = "0.0.0" +description = "Type definitions for the type system and entity validation based on schemas" +optional = false +python-versions = "^3.11" +files = [] +develop = true + +[package.dependencies] +pydantic = "^2.4.2" +pydantic_core = "^2.10.1" +python-slugify = "^8.0.1" +types-python-slugify = "^8.0" + +[package.source] +type = "directory" +url = "../../hash-graph-types/python" + +[[package]] +name = "httpcore" +version = "0.18.0" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"}, + {file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"}, +] + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = "==1.*" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "httpx" +version = "0.25.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"}, + {file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"}, +] + +[package.dependencies] +certifi = "*" +httpcore = ">=0.18.0,<0.19.0" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pydantic" +version = "2.4.2" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, + {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.10.1" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.10.1" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, + {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, + {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, + {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, + {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, + {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, + {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, + {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, + {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, + {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, + {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, + {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, + {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, + {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, + {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, + {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "python-slugify" +version = "8.0.1" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, + {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + +[[package]] +name = "ruff" +version = "0.1.2" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.2-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:0d3ee66b825b713611f89aa35d16de984f76f26c50982a25d52cd0910dff3923"}, + {file = "ruff-0.1.2-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f85f850a320ff532b8f93e8d1da6a36ef03698c446357c8c43b46ef90bb321eb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:809c6d4e45683696d19ca79e4c6bd3b2e9204fe9546923f2eb3b126ec314b0dc"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46005e4abb268e93cad065244e17e2ea16b6fcb55a5c473f34fbc1fd01ae34cb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10cdb302f519664d5e2cf954562ac86c9d20ca05855e5b5c2f9d542228f45da4"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f89ebcbe57a1eab7d7b4ceb57ddf0af9ed13eae24e443a7c1dc078000bd8cc6b"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7344eaca057d4c32373c9c3a7afb7274f56040c225b6193dd495fcf69453b436"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dffa25f6e03c4950b6ac6f216bc0f98a4be9719cb0c5260c8e88d1bac36f1683"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42ddaea52cb7ba7c785e8593a7532866c193bc774fe570f0e4b1ccedd95b83c5"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8533efda625bbec0bf27da2886bd641dae0c209104f6c39abc4be5b7b22de2a"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b0b1b82221ba7c50e03b7a86b983157b5d3f4d8d4f16728132bdf02c6d651f77"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c1362eb9288f8cc95535294cb03bd4665c8cef86ec32745476a4e5c6817034c"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ffa7ef5ded0563329a35bd5a1cfdae40f05a75c0cc2dd30f00b1320b1fb461fc"}, + {file = "ruff-0.1.2-py3-none-win32.whl", hash = "sha256:6e8073f85e47072256e2e1909f1ae515cf61ff5a4d24730a63b8b4ac24b6704a"}, + {file = "ruff-0.1.2-py3-none-win_amd64.whl", hash = "sha256:b836ddff662a45385948ee0878b0a04c3a260949905ad861a37b931d6ee1c210"}, + {file = "ruff-0.1.2-py3-none-win_arm64.whl", hash = "sha256:b0c42d00db5639dbd5f7f9923c63648682dd197bf5de1151b595160c96172691"}, + {file = "ruff-0.1.2.tar.gz", hash = "sha256:afd4785ae060ce6edcd52436d0c197628a918d6d09e3107a892a1bad6a4c6608"}, +] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + +[[package]] +name = "types-python-slugify" +version = "8.0.0.3" +description = "Typing stubs for python-slugify" +optional = false +python-versions = "*" +files = [ + {file = "types-python-slugify-8.0.0.3.tar.gz", hash = "sha256:868e6610ab9a01c01b2ccc1b982363e694d6bbb4fcf32e0d82688c89dceb4e2c"}, + {file = "types_python_slugify-8.0.0.3-py3-none-any.whl", hash = "sha256:2353c161c79ab6cce955b50720c6cd03586ec297558122236d130e4a19f21209"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "901e0f877711bdb1830e251e1d315406aabe994e48c90731a6c0346cbfbeff08" diff --git a/libs/hash-graph-sdk/python/poetry.toml b/libs/hash-graph-sdk/python/poetry.toml new file mode 100644 index 0000000..a5f04e6 --- /dev/null +++ b/libs/hash-graph-sdk/python/poetry.toml @@ -0,0 +1,3 @@ +[virtualenvs] +name = ".venv" +in-project = true diff --git a/libs/hash-graph-sdk/python/pyproject.toml b/libs/hash-graph-sdk/python/pyproject.toml new file mode 100644 index 0000000..50a2d8f --- /dev/null +++ b/libs/hash-graph-sdk/python/pyproject.toml @@ -0,0 +1,90 @@ +[tool.poetry] +name = "hash-graph-sdk" +version = "0.0.0" +description = "SDK for the HASH Graph API" +license = "AGPL-3.0-only" +authors = ["HASH"] +readme = "README.md" +packages = [{ include = "graph_sdk" }] + +[tool.poetry.dependencies] +python = "^3.11" + +pydantic = "^2.4.2" +yarl = "^1.9.2" + +[tool.poetry.group.dev.dependencies] +setuptools = "^68.2.2" +devtools = "^0.12.2" + +[tool.poetry.group.lint-tools.dependencies] +black = "^23.10.1" +ruff = "^0.1.2" +mypy = "^1.6.1" + +hash-graph-client = { path = "../../hash-graph-client/python", develop = true } +hash-graph-types = { path = "../../hash-graph-types/python", develop = true } + + +[tool.black] +target-version = ['py311'] +preview = true +extend-exclude = ''' +( + ^/graph_sdk/client/blocking.py$ | ^/graph_sdk/filter/path.py$ +) +''' + +[tool.ruff] +select = ["ALL"] +extend-exclude = ["graph_sdk/client/blocking.py", "graph_sdk/filter/path.py"] +ignore = [ + "D203", # this conflicts with `D211` + "D213", # this conflicts with `D212` + "D401", # Relates to PEP-257 but also conflicts with Google Python Style Guide, generally gets in the way + "ANN101", # most type checkers infer the type of `self` automatically + "ANN102", # most type checkers infer the type of `cls` automatically + "FIX002", # TODOs should be fixed, not removed + "TD002", # We don't add authors to TODO strings + "PLC0414", # Conflicts with `no_implicit_reexport = true` +] + +target-version = "py311" + +[tool.mypy] +plugins = "pydantic.mypy" + +disallow_untyped_defs = true +disallow_any_unimported = true +no_implicit_optional = true +check_untyped_defs = true +no_implicit_reexport = true +strict_optional = true +show_error_codes = true +show_traceback = true +strict_equality = true + +# warnings +warn_unused_configs = true +warn_return_any = true +warn_incomplete_stub = true +warn_unreachable = true +warn_redundant_casts = true +warn_unused_ignores = true + +# error messages +pretty = true +color_output = true +error_summary = true +incremental = true + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/libs/hash-graph-sdk/python/scripts/generate_blocking.py b/libs/hash-graph-sdk/python/scripts/generate_blocking.py new file mode 100644 index 0000000..97268aa --- /dev/null +++ b/libs/hash-graph-sdk/python/scripts/generate_blocking.py @@ -0,0 +1,219 @@ +# type: ignore +"""Script to generate the blocking implementation of the client.""" + +import ast +from pathlib import Path + +ROOT = Path(__file__).parent.parent + +concurrent_contents = (ROOT / "graph_sdk" / "client" / "concurrent.py").read_text() +blocking_ast = ast.parse(concurrent_contents, "concurrent.py", type_comments=True) + +# The transformation that we want to do is pretty simple: +# * copy over all contents, pick the HASHClient class +# * add imports to utils and the concurrent client +# * go over each method that is sync, call the inner client instead +# * go over each async method, wrap it in a sync method + +# generate a new top level type comment for the blocking client +blocking_ast_doc: ast.Expr = blocking_ast.body[0] + +blocking_ast_doc.value = ast.Constant(value="""Blocking API for the Graph SDK. + +This is just a thin wrapper around the async API. + +(Usually, one could achieve this by simply wrapping the async API automatically, +the problem with that approach however is that users loose the ability to look +at the source code) +""") + +# add imports to utils and the concurrent client +blocking_ast.body.insert( + 1, + ast.ImportFrom( + module="graph_sdk.utils", + names=[ast.alias(name="async_to_sync")], + ), +) +blocking_ast.body.insert( + 1, + ast.ImportFrom( + module="graph_sdk.client.concurrent", + names=[ast.alias(name="HASHClient", asname="ConcurrentHASHClient")], + ), +) + +# find the HASHClient class +client_ast: ast.ClassDef = next( + statement for statement in blocking_ast.body if isinstance(statement, ast.ClassDef) +) + +# remove all field annotations (AnnAssign) +client_ast.body = [ + statement + for statement in client_ast.body + if not isinstance(statement, ast.AnnAssign) +] + + +# add a new field annotation for the inner client +client_ast.body.insert( + 1, + ast.AnnAssign( + target=ast.Name(id="inner", ctx=ast.Store()), + annotation=ast.Name(id="ConcurrentHASHClient", ctx=ast.Load()), + simple=1, + ), +) + +# change the __init__ method to just init the inner client +client_init = next( + statement + for statement in client_ast.body + if isinstance(statement, ast.FunctionDef) and statement.name == "__init__" +) + +client_init_args = client_init.args + +client_init.body = [ + client_init.body[0], + ast.Assign( + targets=[ + ast.Attribute( + value=ast.Name(id="self", ctx=ast.Load()), + attr="inner", + ctx=ast.Store(), + ), + ], + value=ast.Call( + func=ast.Name(id="ConcurrentHASHClient", ctx=ast.Load()), + args=[ + ast.Name(arg.arg) for arg in client_init_args.args if arg.arg != "self" + ], + keywords=[], + ), + ), +] + + +def call_inner(function_def: ast.FunctionDef) -> ast.Call: + """Call the inner client method.""" + args = function_def.args + + return ast.Call( + func=( + ast.Attribute( + value=ast.Attribute( + value=ast.Name(id="self", ctx=ast.Load()), + attr="inner", + ctx=ast.Load(), + ), + attr=function_def.name, + ctx=ast.Load(), + ) + ), + args=[ + ast.Name(arg.arg, ctx=ast.Load()) for arg in args.args if arg.arg != "self" + ], + keywords=[ + ast.keyword(arg=keyword.arg, value=ast.Name(keyword.arg, ctx=ast.Load())) + for keyword in (args.kwarg or []) + ], + ) + + +# # go over each method that is sync, call the inner client instead +for method in client_ast.body: + if not isinstance(method, ast.FunctionDef): + continue + + if method.name in ("__init__", "__doc__", "actor"): + continue + + method_args = method.args + + method.body = [ + method.body[0], + ast.Return(value=call_inner(method)), + ] + +# go over each async method, wrap it in the async_to_sync method and return it +for method in client_ast.body: + if not isinstance(method, ast.AsyncFunctionDef): + continue + + method_args = method.args + method_name = method.name + method_doc = method.body[0] + method_returns = method.returns + + client_ast.body.append( + ast.FunctionDef( + name=method_name, + args=method_args, + body=[ + method_doc, + ast.Return( + value=ast.Call( + func=ast.Name(id="async_to_sync", ctx=ast.Load()), + args=[ + ast.Call( + func=ast.Attribute( + value=ast.Attribute( + value=ast.Name(id="self", ctx=ast.Load()), + attr="inner", + ctx=ast.Load(), + ), + attr=method.name, + ctx=ast.Load(), + ), + args=[ + ast.Name(arg.arg, ctx=ast.Load()) + for arg in method_args.args + if arg.arg != "self" + ], + keywords=[ + ast.keyword( + arg=keyword.arg, + value=ast.Name(keyword.arg, ctx=ast.Load()), + ) + for keyword in ( + (method_args.kwarg or []) + + (method_args.kwonlyargs or []) + ) + ], + ), + ], + keywords=[], + ), + ), + ], + returns=method_returns, + decorator_list=[], + ), + ) + +# remove all async methods +client_ast.body = [ + statement + for statement in client_ast.body + if not isinstance(statement, ast.AsyncFunctionDef) +] + +# remove with_actor and assert_not_none +blocking_ast.body = [ + statement + for statement in blocking_ast.body + if not ( + isinstance(statement, ast.FunctionDef) + and statement.name in ("with_actor", "assert_not_none") + ) +] + +output = ast.unparse(ast.fix_missing_locations(blocking_ast)) +(ROOT / "graph_sdk" / "client" / "blocking.py").write_text(f""" +# ========================================= +# THIS FILE IS GENERATED, DO NOT CHANGE IT! +# ========================================= + +{output}""") diff --git a/libs/hash-graph-sdk/python/scripts/generate_filter.py b/libs/hash-graph-sdk/python/scripts/generate_filter.py new file mode 100644 index 0000000..52f5e16 --- /dev/null +++ b/libs/hash-graph-sdk/python/scripts/generate_filter.py @@ -0,0 +1,618 @@ +"""Generate `graph_sdk.filter.path` from `graph_client.models`. + +We need to generate 4 classes: + +- DataTypeQueryPath +- PropertyTypeQueryPath +- EntityTypeQueryPath +- EntityQueryPath + +To generate them we have a configuration file that is located +under `graph_sdk/filter/config.json`. + +The configuration file is a record with the following fields: +- `data_type` +- `property_type` +- `entity_type` +- `entity` + +Each entry has the following fields: +- `selector`: Fields that require an intermediary selector, and then continue + with another type. It is a record, where the key is the field name + and the value is the type to continue with. + (one of `data_type`, `property_type`, `entity_type`, `entity`) +- `untyped`: Fields that go into untyped territory through the properties selector. +- `direct`: Fields that do not require an intermediary selector, and then continue + with another type. It is a record, where the key is the field name and the + value is the type to continue with. + (one of `data_type`, `property_type`, `entity_type`, `entity`) +- `arguments`: Fields that have (optional) arguments, + these arguments follow as `key-value` pairs after the name of the property. +""" +# ruff: noqa: ERA001 +import ast +import json +from enum import Enum +from pathlib import Path +from typing import Literal, TypedDict, assert_never + +from graph_client.models import ( + DataTypeQueryToken, + EntityQueryToken, + EntityTypeQueryToken, + PropertyTypeQueryToken, +) + +DIRECTORY = Path(__file__).parent.parent + +TypeId = Literal["data_type", "property_type", "entity_type", "entity"] + + +class Argument(TypedDict): + """Type information for an argument.""" + + type: Literal["uint"] + required: bool + + +class Meta(TypedDict): + """Additional configuration file information.""" + + arguments: dict[str, Argument] + + +class ConfigurationEntry(TypedDict): + """A configuration entry.""" + + selector: dict[str, TypeId] + untyped: list[str] + direct: dict[str, TypeId] + arguments: dict[str, list[str]] + + +class Configuration(TypedDict): + """The configuration file.""" + + meta: Meta + + data_type: ConfigurationEntry + property_type: ConfigurationEntry + entity_type: ConfigurationEntry + entity: ConfigurationEntry + + +def is_builtin(name: str) -> bool: + """Check if the given name is a builtin.""" + return name in dir(__builtins__) + + +def is_keyword(name: str) -> bool: + """Check if the given name is a keyword.""" + try: + ast.parse(f"def {name}(): ...") + except SyntaxError: + return True + + return False + + +def is_keyword_or_builtin(name: str) -> bool: + """Check if the given name is a keyword or builtin.""" + return is_builtin(name) or is_keyword(name) + + +def to_snake_case(name: str) -> str: + """Convert a camel case name to snake case.""" + return "".join( + f"_{char.lower()}" if char.isupper() else char for char in name + ).lstrip("_") + + +def get_class_name( + name: Literal["data_type", "property_type", "entity_type", "entity"], +) -> str: + """Get the class name for the given name.""" + return { + "data_type": "DataTypeQueryPath", + "property_type": "PropertyTypeQueryPath", + "entity_type": "EntityTypeQueryPath", + "entity": "EntityQueryPath", + }[name] + + +def get_human_readable_name(token: Enum) -> str: + """Get the human readable name for the given token.""" + return { + "DataTypeQueryToken": "a data type", + "PropertyTypeQueryToken": "a property type", + "EntityTypeQueryToken": "an entity type", + "EntityQueryToken": "an entity", + }[type(token).__name__] + + +def load_attribute( + path: list[str], + ctx: ast.Load | ast.Store | None = None, +) -> ast.Attribute | ast.Name: + """Create a dotted attribute.""" + if len(path) == 1: + return ast.Name(id=path[0], ctx=ctx) + + return ast.Attribute( + value=load_attribute(path[:-1], ctx=ctx), + attr=path[-1], + ctx=ast.Load(), + ) + + +def argument_annotation(argument: Argument) -> ast.expr: + """Generate the annotation for an argument.""" + type_ = None + + if argument["type"] == "uint": + type_ = ast.Name(id="int", ctx=ast.Load()) + + if type_ is None: + assert_never(argument["type"]) + + if not argument["required"]: + return ast.BinOp(left=type_, op=ast.BitOr(), right=ast.Name(id="None")) + + return type_ + + +def create_method( + *, + name: str, + args: dict[str, Argument], + body: list[ast.stmt], + returns: ast.expr, +) -> ast.FunctionDef: + """Create a method with arguments.""" + keywords = [ + ast.arg(arg=to_snake_case(name), annotation=argument_annotation(info)) + for name, info in args.items() + ] + + keyword_defaults = [ + None if info["required"] else ast.Constant(value=None) for info in args.values() + ] + + return ast.FunctionDef( + name=name, + args=ast.arguments( + posonlyargs=[], + args=[ast.arg(arg="self", annotation=None)], + vararg=None, + kwonlyargs=keywords, + kw_defaults=keyword_defaults, + kwarg=None, + defaults=[], + ), + body=body, + decorator_list=[], + returns=returns, + ) + + +def generate_method_docstring( + token: Enum, + name: str, +) -> ast.Expr: + """Generate a docstring for the given method.""" + return ast.Expr( + value=ast.Constant( + value=( + f"Return the path to the {name} attribute " + f"of {get_human_readable_name(token)}." + ), + ), + ) + + +def generate_method_argument_body(args: dict[str, Argument]) -> list[ast.stmt]: + """Generate the body for the method arguments.""" + if not args: + return [] + + # we need to create additional body statements, that will compile to: + # args = [] + # if is not None: + # args.append(f"{}={}") + # + statements: list[ast.stmt] = [ + ast.Assign( + [ast.Name(id="args", ctx=ast.Store())], + ast.List(elts=[], ctx=ast.Load()), + ), + ] + + for name, info in args.items(): + variable = ast.Name(id=to_snake_case(name), ctx=ast.Load()) + + append_value = ast.JoinedStr( + values=[ + ast.Constant(value=f"{name}="), + ast.FormattedValue(value=variable, conversion=-1, format_spec=None), + ], + ) + + if info["required"]: + statements.append( + ast.Expr( + value=ast.Call( + func=load_attribute(["args", "append"]), + args=[append_value], + keywords=[], + ), + ), + ) + else: + statements.append( + ast.If( + test=ast.Compare( + left=variable, + ops=[ast.IsNot()], + comparators=[ast.Name(id="None", ctx=ast.Load())], + ), + body=[ + ast.Expr( + value=ast.Call( + func=load_attribute(["args", "append"]), + args=[append_value], + keywords=[], + ), + ), + ], + orelse=[], + ), + ) + + return statements + + +def generate_push_call(token: Enum, name: str, args: dict[str, Argument]) -> ast.Call: + """Generate the call to push.""" + if not args: + return ast.Call( + func=load_attribute(["self", "path", "push"]), + args=[load_attribute([type(token).__name__, name])], + keywords=[], + ) + + # we need to generate: + # self.path.push(f"{.}({ ", ".join() })" + # if args else .) + return ast.Call( + func=load_attribute(["self", "path", "push"]), + args=[ + ast.IfExp( + test=ast.Name(id="args", ctx=ast.Load()), + body=ast.JoinedStr( + values=[ + ast.FormattedValue( + value=load_attribute([type(token).__name__, name]), + conversion=-1, + format_spec=None, + ), + ast.Constant(value="("), + ast.FormattedValue( + value=ast.Call( + func=ast.Attribute( + value=ast.Constant(value=", "), + attr="join", + ), + args=[ast.Name(id="args", ctx=ast.Load())], + keywords=[], + ), + conversion=-1, + format_spec=None, + ), + ast.Constant(value=")"), + ], + ), + orelse=load_attribute([type(token).__name__, name]), + ), + ], + keywords=[], + ) + + +def generate_plain_method( + token: Enum, + name: str, + args: dict[str, Argument], +) -> ast.FunctionDef: + """Generate a method that ends the path.""" + function_name = name + while is_keyword_or_builtin(function_name): + function_name += "_" + + return create_method( + name=function_name, + body=[ + generate_method_docstring(token, name), + *generate_method_argument_body(args), + ast.Return(value=generate_push_call(token, name, args)), + ], + args=args, + returns=ast.Name(id="Path", ctx=ast.Load()), + ) + + +def generate_selector_method( + class_name: str, + token: Enum, + name: str, + args: dict[str, Argument], + next_type: TypeId, +) -> ast.FunctionDef: + """Generate a method that continues the path after a selector to a type.""" + next_class_name = get_class_name(next_type) + next_class_name_set: ast.expr = ast.Name(id=next_class_name, ctx=ast.Load()) + + if class_name == next_class_name: + next_class_name = "Self" + next_class_name_set = ast.Call( + func=ast.Name(id="type", ctx=ast.Load()), + args=[ast.Name(id="self", ctx=ast.Load())], + keywords=[], + ) + + function_name = name + while is_keyword_or_builtin(function_name): + function_name += "_" + + return create_method( + name=function_name, + body=[ + generate_method_docstring(token, name), + *generate_method_argument_body(args), + ast.Return( + value=ast.Call( + func=ast.Attribute( + ast.Call( + func=ast.Attribute( + value=ast.Subscript( + value=ast.Name( + id="SelectorQueryPath", + ctx=ast.Load(), + ), + slice=ast.Name(id=next_class_name, ctx=ast.Load()), + ), + attr="from_path", + ctx=ast.Load(), + ), + args=[generate_push_call(token, name, args)], + keywords=[], + ), + attr="set_cls", + ctx=ast.Load(), + ), + args=[next_class_name_set], + keywords=[], + ), + ), + ], + args=args, + returns=ast.Subscript( + value=ast.Name(id="SelectorQueryPath", ctx=ast.Load()), + slice=ast.Name(id=next_class_name), + ), + ) + + +def generate_untyped_method( + token: Enum, + name: str, + args: dict[str, Argument], +) -> ast.FunctionDef: + """Generate a method that continues the path with a wildcard selector.""" + function_name = name + while is_keyword_or_builtin(function_name): + function_name += "_" + + return create_method( + name=function_name, + body=[ + generate_method_docstring(token, name), + *generate_method_argument_body(args), + ast.Return( + value=ast.Call( + func=load_attribute(["UntypedQueryPath", "from_path"]), + args=[generate_push_call(token, name, args)], + keywords=[], + ), + ), + ], + args=args, + returns=ast.Name(id="UntypedQueryPath", ctx=ast.Load()), + ) + + +def generate_direct_method( + class_name: str, + token: Enum, + name: str, + args: dict[str, Argument], + next_type: TypeId, +) -> ast.FunctionDef: + """Generate a method that continues the path with the specified type.""" + next_class_name = get_class_name(next_type) + call_from_path_on = next_class_name + + if class_name == next_class_name: + next_class_name = "Self" + call_from_path_on = "self" + + function_name = name + while is_keyword_or_builtin(function_name): + function_name += "_" + + return create_method( + name=function_name, + body=[ + generate_method_docstring(token, name), + *generate_method_argument_body(args), + ast.Return( + value=ast.Call( + func=load_attribute([call_from_path_on, "from_path"]), + args=[generate_push_call(token, name, args)], + keywords=[], + ), + ), + ], + args=args, + returns=ast.Name(id=next_class_name, ctx=ast.Load()), + ) + + +def generate_method( + class_name: str, + tokens: Enum, + method_name: str, + *, + config: ConfigurationEntry, + meta: Meta, +) -> ast.FunctionDef: + """Generate a method for a path class.""" + arguments = config["arguments"].get(method_name, []) + args = {key: meta["arguments"][key] for key in arguments} + + if selector := config["selector"].get(method_name, None): + return generate_selector_method(class_name, tokens, method_name, args, selector) + + if method_name in config["untyped"]: + return generate_untyped_method(tokens, method_name, args) + + if direct := config["direct"].get(method_name, None): + return generate_direct_method(class_name, tokens, method_name, args, direct) + + return generate_plain_method(tokens, method_name, args) + + +def generate_path( + id_: TypeId, + config: ConfigurationEntry, + meta: Meta, +) -> ast.ClassDef: + """Generate a path class.""" + class_name = get_class_name(id_) + + tokens: type[Enum] = { + "data_type": DataTypeQueryToken, + "property_type": PropertyTypeQueryToken, + "entity_type": EntityTypeQueryToken, + "entity": EntityQueryToken, + }[id_] + + body = [ + generate_method( + class_name, + token, + token.name, + config=config, + meta=meta, + ) + for token in tokens + ] + + return ast.ClassDef( + name=class_name, + bases=[ast.Name(id="AbstractQueryPath", ctx=ast.Load())], + keywords=[], + body=[ + ast.Expr( + value=ast.Constant( + value=( + "A query path for" + f" {get_human_readable_name(next(iter(tokens)))}." + ), + ), + ), + *body, + ], + decorator_list=[], + ) + + +def imports() -> list[ast.ImportFrom]: + """Generate the imports for the module.""" + return [ + ast.ImportFrom( + module="typing", + names=[ + ast.alias(name="Self", asname=None), + ], + ), + ast.ImportFrom( + module="graph_client.models", + names=[ + ast.alias(name="DataTypeQueryToken", asname=None), + ast.alias(name="PropertyTypeQueryToken", asname=None), + ast.alias(name="EntityTypeQueryToken", asname=None), + ast.alias(name="EntityQueryToken", asname=None), + ], + ), + ast.ImportFrom( + module="graph_sdk.filter.base", + names=[ + ast.alias(name="AbstractQueryPath", asname=None), + ast.alias(name="UntypedQueryPath", asname=None), + ast.alias(name="SelectorQueryPath", asname=None), + ], + ), + ast.ImportFrom( + module="graph_sdk.query", + names=[ + ast.alias(name="Path", asname=None), + ], + ), + ] + + +def doc_comment() -> ast.Expr: + """Add a doc comment to the top of the file.""" + return ast.Expr( + value=ast.Constant( + value=( + "Definitions for all path objects.\n\nThis file is auto-generated. Do" + " not edit!" + ), + ), + ) + + +configuration: Configuration = json.loads( + (DIRECTORY / "graph_sdk" / "filter" / "config.json").read_text(), +) + + +module = ast.Module( + body=[ + doc_comment(), + *imports(), + generate_path("data_type", configuration["data_type"], configuration["meta"]), + generate_path( + "property_type", + configuration["property_type"], + configuration["meta"], + ), + generate_path( + "entity_type", + configuration["entity_type"], + configuration["meta"], + ), + generate_path("entity", configuration["entity"], configuration["meta"]), + ], + type_ignores=[], +) + +output = ast.unparse(ast.fix_missing_locations(module)) + +(DIRECTORY / "graph_sdk" / "filter" / "path.py").write_text(f""" +# ========================================= +# THIS FILE IS GENERATED, DO NOT CHANGE IT! +# ========================================= + +{output}""") diff --git a/libs/hash-graph-sdk/python/turbo.json b/libs/hash-graph-sdk/python/turbo.json new file mode 100644 index 0000000..fbe9ae6 --- /dev/null +++ b/libs/hash-graph-sdk/python/turbo.json @@ -0,0 +1,56 @@ +{ + "extends": ["//"], + "pipeline": { + "codegen:blocking": { + "inputs": [ + "./graph_sdk/client/concurrent.py", + "./scripts/generate_blocking.py" + ], + "outputs": ["./graph_sdk/client/blocking.py"] + }, + "codegen:filter": { + "inputs": [ + "../../../../apps/hash-graph/openapi/openapi.json", + "./scripts/generate_filter.py" + ], + "outputs": ["./graph_sdk/filter/path.py"] + }, + "build": { + "dependsOn": ["^build", "codegen"], + "inputs": ["./**/*.py", "pyproject.toml", "poetry.lock", "LICENSE*"], + "outputs": ["dist/**"] + }, + "poetry:venv": { + "cache": false + }, + "poetry:install": { + "cache": false + }, + "poetry:install-production": { + "cache": false + }, + "fix:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"], + "outputs": ["poetry.lock"] + }, + "lint:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"] + }, + "lint:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:mypy": { + "dependsOn": ["build"], + "inputs": ["./**/*.py", "pyproject.toml"] + } + } +} diff --git a/libs/hash-graph-types/python/LICENSE.md b/libs/hash-graph-types/python/LICENSE.md new file mode 100644 index 0000000..9a70d79 --- /dev/null +++ b/libs/hash-graph-types/python/LICENSE.md @@ -0,0 +1,606 @@ +# GNU Affero General Public License + +_Version 3, 19 November 2007_ +_Copyright © 2007 Free Software Foundation, Inc. <>_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +## Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: **(1)** assert copyright on the software, and **(2)** offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions + +“This License” refers to version 3 of the GNU Affero General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based +on the Program. + +To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that **(1)** displays an appropriate copyright notice, and **(2)** +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code + +The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work. + +A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other +than the work as a whole, that **(a)** is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and **(b)** serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +### 2. Basic Permissions + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +### 4. Conveying Verbatim Copies + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +- **a)** The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- **b)** The work must carry prominent notices stating that it is + released under this License and any conditions added under section 7. + This requirement modifies the requirement in section 4 to + “keep intact all notices”. +- **c)** You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- **d)** If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +- **a)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- **b)** Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either **(1)** a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or **(2)** access to copy the + Corresponding Source from a network server at no charge. +- **c)** Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- **d)** Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- **e)** Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A “User Product” is either **(1)** a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or **(2)** anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms + +“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +- **a)** Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- **b)** Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- **c)** Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- **d)** Limiting the use for publicity purposes of names of licensors or + authors of the material; or +- **e)** Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- **f)** Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + +All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +### 8. Termination + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated **(a)** +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and **(b)** permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents + +A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either **(1)** cause the Corresponding Source to be so +available, or **(2)** arrange to deprive yourself of the benefit of the +patent license for this particular work, or **(3)** arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license **(a)** in connection with copies of the covered work +conveyed by you (or copies made from those copies), or **(b)** primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16 + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. diff --git a/libs/hash-graph-types/python/README.md b/libs/hash-graph-types/python/README.md new file mode 100644 index 0000000..175ab51 --- /dev/null +++ b/libs/hash-graph-types/python/README.md @@ -0,0 +1,3 @@ +# HASH Graph types + +Utility library to convert Block Protocol ontology schemas to Python Pydantic models. diff --git a/libs/hash-graph-types/python/graph_types/__init__.py b/libs/hash-graph-types/python/graph_types/__init__.py new file mode 100644 index 0000000..9194706 --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/__init__.py @@ -0,0 +1,61 @@ +"""Replicates the Block Protocol type system for use in Python.""" + +from typing import Protocol +from uuid import UUID + +# This solution is not great as it _could_ lead to circular imports. However, +# it is the best solution we have for now. The alternative is to have a single +# file that contains all the schemas, but that is not very maintainable. +# +# If we run into issues with circular imports, we can refactor this to use +# direct imports. For example, instead of importing `DataTypeSchema` from +# `graph_types`, we can import it from `graph_types.data_type`. +from .data_type import DataTypeReference as DataTypeReference +from .data_type import DataTypeSchema as DataTypeSchema +from .entity_type import EntityTypeReference as EntityTypeReference +from .entity_type import EntityTypeSchema as EntityTypeSchema +from .property_type import PropertyTypeReference as PropertyTypeReference +from .property_type import PropertyTypeSchema as PropertyTypeSchema + + +class GraphAPIProtocol(Protocol): + """Defines the interface for a graph API.""" + + async def get_data_type( + self, + data_type_id: str, + *, + actor_id: UUID, + ) -> DataTypeSchema: + """Returns the data type schema for the given data type ID. + + If the data type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + """ + ... + + async def get_property_type( + self, + property_type_id: str, + *, + actor_id: UUID, + ) -> PropertyTypeSchema: + """Returns the property type schema for the given property type ID. + + If the property type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + """ + ... + + async def get_entity_type( + self, + entity_type_id: str, + *, + actor_id: UUID, + ) -> EntityTypeSchema: + """Returns the entity type schema for the given entity type ID. + + If the entity type is not found it will attempt to fetch it and use + the actor ID to authenticate the request. + """ + ... diff --git a/libs/hash-graph-types/python/graph_types/_annotations/__init__.py b/libs/hash-graph-types/python/graph_types/_annotations/__init__.py new file mode 100644 index 0000000..623ff0a --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/_annotations/__init__.py @@ -0,0 +1,4 @@ +from .const import constant +from .require import not_required + +__all__ = ["constant", "not_required"] diff --git a/libs/hash-graph-types/python/graph_types/_annotations/const.py b/libs/hash-graph-types/python/graph_types/_annotations/const.py new file mode 100644 index 0000000..65810ef --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/_annotations/const.py @@ -0,0 +1,68 @@ +from typing import Annotated, Any, TypeVar, cast, overload + +from pydantic import GetCoreSchemaHandler, GetJsonSchemaHandler +from pydantic.json_schema import JsonSchemaValue +from pydantic_core import CoreSchema, core_schema + +T = TypeVar("T") + + +class ConstAnnotation: + const: Any + + @classmethod + def __get_pydantic_core_schema__( + cls, + source_type: Any, # noqa: ANN401 + handler: GetCoreSchemaHandler, + ) -> CoreSchema: + schema = handler(source_type) + + return core_schema.no_info_after_validator_function( + cls.validate_const, + schema, + ) + + @classmethod + def __get_pydantic_json_schema__( + cls, + schema: CoreSchema, + handler: GetJsonSchemaHandler, + ) -> JsonSchemaValue: + json_schema = handler(schema) + json_schema.update(const=cls.const) + + return json_schema + + @classmethod + def validate_const(cls, v: T) -> T: + if v != cls.const: + msg = f"Value must be {cls.const}" + raise ValueError(msg) + + return v + + +_Undefined = object() + + +@overload +def constant(const_: T, /) -> type[T]: ... + + +@overload +def constant(type_: type[T], const_: T, /) -> type[T]: ... + + +def constant(type_: type[T] | T, const_: T | object = _Undefined, /) -> type[T]: + if const_ is _Undefined: + value = cast(T, type_) + ty = cast(type[T], type(const_)) + else: + value = cast(T, const_) + ty = cast(type[T], type_) + + class Annotation(ConstAnnotation): + const = value + + return cast(type[T], Annotated[ty, Annotation]) diff --git a/libs/hash-graph-types/python/graph_types/_annotations/require.py b/libs/hash-graph-types/python/graph_types/_annotations/require.py new file mode 100644 index 0000000..6cf5b12 --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/_annotations/require.py @@ -0,0 +1,22 @@ +from typing import Annotated, Any, TypeVar, cast + +from pydantic import GetCoreSchemaHandler +from pydantic_core import CoreSchema, core_schema + +T = TypeVar("T") + + +class NotRequiredAnnotation: + @classmethod + def __get_pydantic_core_schema__( + cls, + source_type: Any, # noqa: ANN401 + handler: GetCoreSchemaHandler, + ) -> CoreSchema: + schema = handler(source_type) + + return core_schema.nullable_schema(schema) + + +def not_required(type_: type[T]) -> type[T]: + return cast(type[T], Annotated[type_, NotRequiredAnnotation]) diff --git a/libs/hash-graph-types/python/graph_types/_schema.py b/libs/hash-graph-types/python/graph_types/_schema.py new file mode 100644 index 0000000..c714f24 --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/_schema.py @@ -0,0 +1,205 @@ +import asyncio +from abc import ABC, abstractmethod +from collections.abc import Awaitable +from typing import TYPE_CHECKING, Annotated, Any, Generic, Literal, TypeVar, cast +from uuid import UUID + +from pydantic import ( + BaseModel, + ConfigDict, + Field, + GetJsonSchemaHandler, + conlist, + create_model, +) +from pydantic.fields import FieldInfo +from pydantic.json_schema import JsonSchemaValue +from pydantic_core import CoreSchema + +from ._annotations import not_required + +if TYPE_CHECKING: + from . import GraphAPIProtocol + from .base import OntologyTypeInfo + + +class Schema(BaseModel, ABC): + @abstractmethod + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type[BaseModel] | Annotated[Any, ...]: # noqa: ANN401 + ... + + +class OntologyTypeSchema(Schema, ABC): + """Common base class for all ontology types.""" + + identifier: str = Field(..., alias="$id") + title: str + description: str | None = None + kind: Literal["dataType", "propertyType", "entityType"] + schema_url: str = Field(..., alias="$schema") + + def type_info(self) -> "OntologyTypeInfo": + from .base import OntologyTypeInfo + + return OntologyTypeInfo( + identifier=self.identifier, + title=self.title, + description=self.description, + kind=self.kind, + schema_url=self.schema_url, + ) + + +T = TypeVar("T", bound=Schema) + + +class OneOf(Schema, Generic[T]): + one_of: list[T] = Field(..., alias="oneOf") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> object: + types = await asyncio.gather( + *[ + value.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + for value in self.one_of + ], + ) + + union = None + for type_ in types: + union = type_ if union is None else union | type_ + + if union is None: + msg = "No types provided" + raise ValueError(msg) + + class OneOfSchema: + @classmethod + def __get_pydantic_json_schema__( + cls, + schema: CoreSchema, + handler: GetJsonSchemaHandler, + ) -> JsonSchemaValue: + json_schema = handler(schema) + if any_of := json_schema.pop("anyOf", None): + json_schema["oneOf"] = any_of + return json_schema + + return Annotated[union, OneOfSchema] + + +class Array(Schema, Generic[T]): + ty: Literal["array"] = Field(..., alias="type") + items: T + min_items: int | None = Field(default=None, alias="minItems") + max_items: int | None = Field(default=None, alias="maxItems") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type[list[BaseModel]]: + type_items = await self.items.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + type_ = conlist( + type_items, + min_length=self.min_items, + max_length=self.max_items, + ) + + return cast(type[list[BaseModel]], type_) + + +U = TypeVar("U") + + +class Object(Schema, Generic[T]): + ty: Literal["object"] = Field(..., alias="type") + properties: dict[str, T] + required: list[str] | None = None + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type[BaseModel]: + async def async_value( + key: str, + value: Awaitable[type[BaseModel] | Any], + ) -> tuple[str, type[BaseModel] | Any]: + return key, await value + + def field_type(key: str, type_: type[U]) -> type[U]: + if self.required is None or key not in self.required: + return not_required(type_) + + return type_ + + def schema_extra(extra: dict[str, Any]) -> None: + any_of = extra.pop("anyOf", None) + + extra.clear() + extra.update(any_of[0]) + + def field_info(key: str) -> FieldInfo: + # cast is necessary here because `Field` + # return `FieldInfo`, even though it doesn't. + if self.required is None or key not in self.required: + return cast(FieldInfo, Field(None, json_schema_extra=schema_extra)) + + return cast(FieldInfo, Field(...)) + + types = dict( + await asyncio.gather( + *( + async_value( + key, + value.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ), + ) + for key, value in self.properties.items() + ), + ), + ) + + types = { + key: (field_type(key, value), field_info(key)) + for key, value in types.items() + } + + if additional_properties: + config = ConfigDict(extra="allow") + else: + config = ConfigDict(extra="forbid") + + return create_model( + "DictSchema", + __config__=config, + **types, + ) diff --git a/libs/hash-graph-types/python/graph_types/base.py b/libs/hash-graph-types/python/graph_types/base.py new file mode 100644 index 0000000..747cb23 --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/base.py @@ -0,0 +1,62 @@ +"""Base classes for all graph types created by `.create_model()`. + +These classes are primarily used as markers +""" + +from abc import ABC +from typing import ClassVar + +from pydantic import BaseModel, ConfigDict, Field, GetJsonSchemaHandler +from pydantic.json_schema import JsonSchemaValue +from pydantic_core import CoreSchema + +from . import EntityTypeReference + + +class OntologyTypeInfo(BaseModel): + """Information about a type.""" + + model_config = ConfigDict(populate_by_name=True) + + identifier: str = Field(..., alias="$id") + schema_url: str = Field(..., alias="$schema") + title: str + description: str | None = None + kind: str + + +class OntologyType(BaseModel, ABC): + """Base class for all graph ontology types.""" + + info: ClassVar[OntologyTypeInfo] + + @classmethod + def __get_pydantic_json_schema__( + cls, + schema: CoreSchema, + handler: GetJsonSchemaHandler, + ) -> JsonSchemaValue: + """Update the schema with additional type information.""" + json_schema = handler(schema) + json_schema.update(cls.info.model_dump(by_alias=True)) + return json_schema + + +class EntityTypeInfo(OntologyTypeInfo): + """Information about an entity type.""" + + all_of: list[EntityTypeReference] | None = Field(..., alias="allOf") + + +class EntityType(OntologyType, ABC): + """Base class for all entity types.""" + + info: ClassVar[EntityTypeInfo] + + +class PropertyType(OntologyType, ABC): + """Base class for all property types.""" + + +class DataType(OntologyType, ABC): + """Base class for all data types.""" diff --git a/libs/hash-graph-types/python/graph_types/data_type.py b/libs/hash-graph-types/python/graph_types/data_type.py new file mode 100644 index 0000000..720c20d --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/data_type.py @@ -0,0 +1,122 @@ +"""A data type schema as defined by the Block Protocol.""" + +from typing import ( + TYPE_CHECKING, + Any, + Literal, + TypeAlias, + assert_never, + cast, +) +from uuid import UUID + +from pydantic import ( + BaseModel, + Field, + RootModel, + create_model, +) +from slugify import slugify + +from ._annotations import constant +from ._schema import OntologyTypeSchema, Schema + +if TYPE_CHECKING: + from . import GraphAPIProtocol + from .base import DataType as DataTypeBase + +__all__ = ["DataTypeSchema", "DataTypeReference"] + +DataType: TypeAlias = str | float | bool | None | list[Any] | dict[str, Any] + + +class DataTypeReference(Schema): + """A reference to a data type schema.""" + + ref: str = Field(..., alias="$ref") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type["DataTypeBase"]: + """Creates a model from the referenced data type schema.""" + schema = await graph.get_data_type(self.ref, actor_id=actor_id) + return await schema.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + +class DataTypeSchema(OntologyTypeSchema, extra="allow"): + """A data type schema as defined by the Block Protocol. + + see https://blockprotocol.org/types/modules/graph/0.3/schema/data-type + """ + + kind: Literal["dataType"] + ty: Literal["string", "number", "boolean", "null", "array", "object"] = Field( + ..., + alias="type", + ) + + def _type(self) -> type[DataType]: + match self.ty: + case "string": + return str + case "number": + return float + case "boolean": + return bool + case "null": + return type(None) + case "array": + return list[Any] + case "object": + return dict[str, Any] + case _ as unreachable: + assert_never(unreachable) + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, # noqa: ARG002 + ) -> type["DataTypeBase"]: + """Create an annotated type from this schema.""" + from .base import DataType as DataTypeBase + + # Custom data types will require an actor ID and the graph to be passed in + _actor_id = actor_id + _graph = graph + + type_ = self._type() + if "const" in (self.model_extra or {}): + # `const` can only be in `model_extra`, therefore it is safe to index! + const = self.model_extra["const"] # type: ignore[index] + type_ = constant(type_, const) + + class_name = slugify( + self.identifier, + regex_pattern=r"[^a-z0-9_]+", + separator="_", + ) + + base: type[BaseModel] = type( + f"{class_name}Base", + (DataTypeBase,), + {"info": self.type_info()}, + ) + + return cast( + type[DataTypeBase], + create_model( + class_name, + __base__=(base, RootModel), + root=(type_, Field(...)), + ), + ) diff --git a/libs/hash-graph-types/python/graph_types/entity_type.py b/libs/hash-graph-types/python/graph_types/entity_type.py new file mode 100644 index 0000000..00d1fd2 --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/entity_type.py @@ -0,0 +1,123 @@ +"""An entity type schema as defined by the Block Protocol.""" + +from typing import ( + TYPE_CHECKING, + Any, + Literal, + Never, + cast, +) +from uuid import UUID + +from pydantic import ( + BaseModel, + ConfigDict, + Field, + create_model, +) +from slugify import slugify + +from ._schema import Array, Object, OneOf, OntologyTypeSchema, Schema +from .property_type import PropertyTypeReference + +if TYPE_CHECKING: + from . import GraphAPIProtocol + from .base import EntityType, EntityTypeInfo + +__all__ = ["EntityTypeSchema", "EntityTypeReference"] + + +class EntityTypeReference(Schema): + """A reference to an entity type schema.""" + + ref: str = Field(..., alias="$ref") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type["EntityType"]: + """Creates a model from the referenced entity type schema.""" + schema = await graph.get_entity_type(self.ref, actor_id=actor_id) + return await schema.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + +class EmptyDict(Schema): + model_config = ConfigDict(title=None, extra="forbid") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> Never: + raise NotImplementedError + + +class EntityTypeSchema( + OntologyTypeSchema, + Object[PropertyTypeReference | Array[PropertyTypeReference]], +): + """An entity type schema as defined by the Block Protocol. + + see https://blockprotocol.org/types/modules/graph/0.3/schema/entity-type + """ + + kind: Literal["entityType"] + examples: list[dict[str, Any]] | None = None + links: dict[str, Array[OneOf[EntityTypeReference] | EmptyDict]] | None = None + all_of: list[EntityTypeReference] | None = Field(None, alias="allOf") + + def type_info(self) -> "EntityTypeInfo": + """Return the type information for this schema.""" + from .base import EntityTypeInfo + + original = super().type_info() + + return EntityTypeInfo.model_validate( + (original.model_dump() | {"all_of": self.all_of or []}), + ) + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type["EntityType"]: + """Create an annotated type from this schema.""" + from .base import EntityType + + # Take the fields from Object and create a new model, with a new baseclass. + proxy = await Object.create_model( + self, + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + class_name = slugify( + self.identifier, + regex_pattern=r"[^a-z0-9_]+", + separator="_", + ) + + base: type[BaseModel] = type( + f"{class_name}Base", + (EntityType,), + {"info": self.type_info()}, + ) + + model = create_model( + class_name, + __base__=(base, proxy), + ) + + return cast(type[EntityType], model) diff --git a/libs/hash-graph-types/python/graph_types/property_type.py b/libs/hash-graph-types/python/graph_types/property_type.py new file mode 100644 index 0000000..523080f --- /dev/null +++ b/libs/hash-graph-types/python/graph_types/property_type.py @@ -0,0 +1,115 @@ +"""A property type schema as defined by the Block Protocol.""" + +from typing import ( + TYPE_CHECKING, + Annotated, + Any, + Literal, + cast, +) +from uuid import UUID + +from pydantic import ( + BaseModel, + Field, + RootModel, + create_model, +) +from slugify import slugify + +from ._schema import Array, Object, OneOf, OntologyTypeSchema, Schema +from .data_type import DataTypeReference + +if TYPE_CHECKING: + from . import GraphAPIProtocol + from .base import PropertyType + +__all__ = ["PropertyTypeSchema", "PropertyTypeReference"] + + +class PropertyTypeReference(Schema): + """A reference to a property type schema.""" + + ref: str = Field(..., alias="$ref") + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type["PropertyType"]: + """Creates a model from the referenced property type schema.""" + schema = await graph.get_property_type(self.ref, actor_id=actor_id) + return await schema.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + +class PropertyValue(RootModel, Schema): + root: ( + DataTypeReference + | Object[PropertyTypeReference | Array[PropertyTypeReference]] + | Array[OneOf["PropertyValue"]] + ) + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type[RootModel] | Annotated[Any, ...]: # noqa: ANN401 + return await self.root.create_model( + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + +class PropertyTypeSchema(OntologyTypeSchema, OneOf[PropertyValue]): + """A property type schema as defined by the Block Protocol. + + see https://blockprotocol.org/types/modules/graph/0.3/schema/property-type + """ + + kind: Literal["propertyType"] + + async def create_model( + self, + *, + actor_id: UUID, + graph: "GraphAPIProtocol", + additional_properties: bool, + ) -> type["PropertyType"]: + """Create an annotated type from this schema.""" + from .base import PropertyType + + inner = await OneOf.create_model( + self, + actor_id=actor_id, + graph=graph, + additional_properties=additional_properties, + ) + + class_name = slugify( + self.identifier, + regex_pattern=r"[^a-z0-9_]+", + separator="_", + ) + + base: type[BaseModel] = type( + f"{class_name}Base", + (PropertyType,), + {"info": self.type_info()}, + ) + + model = create_model( + class_name, + __base__=(base, RootModel), + root=(inner, Field(...)), + ) + + return cast(type[PropertyType], model) diff --git a/libs/hash-graph-types/python/graph_types/py.typed b/libs/hash-graph-types/python/graph_types/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/libs/hash-graph-types/python/package.json b/libs/hash-graph-types/python/package.json new file mode 100644 index 0000000..de10003 --- /dev/null +++ b/libs/hash-graph-types/python/package.json @@ -0,0 +1,19 @@ +{ + "name": "@local/hash-graph-types-py", + "version": "0.0.0-private", + "private": true, + "description": "Type definitions for the type system and entity validation based on schemas", + "scripts": { + "build": "poetry build --no-interaction", + "fix:black": "poetry run black graph_types", + "fix:lock-files": "poetry lock --no-update", + "fix:ruff": "poetry run ruff graph_types --fix", + "lint:black": "poetry run black --check --diff --color graph_types", + "lint:lock-files": "poetry lock --check", + "lint:mypy": "poetry run mypy .", + "lint:ruff": "poetry run ruff graph_types", + "poetry:install": "poetry install --no-root --no-interaction", + "poetry:install-production": "poetry install --no-root --no-interaction --only main" + }, + "dependencies": {} +} diff --git a/libs/hash-graph-types/python/poetry.lock b/libs/hash-graph-types/python/poetry.lock new file mode 100644 index 0000000..fdce036 --- /dev/null +++ b/libs/hash-graph-types/python/poetry.lock @@ -0,0 +1,404 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[[package]] +name = "black" +version = "23.10.1" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, + {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, + {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, + {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, + {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, + {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, + {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, + {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, + {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, + {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, + {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.6" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, + {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pydantic" +version = "2.4.2" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, + {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.10.1" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.10.1" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, + {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, + {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, + {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, + {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, + {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, + {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, + {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, + {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, + {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, + {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, + {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, + {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, + {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, + {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, + {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, + {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, + {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, + {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, + {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, + {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, + {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, + {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, + {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, + {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, + {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, + {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, + {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, + {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, + {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, + {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, + {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, + {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, + {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, + {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "python-slugify" +version = "8.0.1" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, + {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + +[[package]] +name = "ruff" +version = "0.1.2" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.2-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:0d3ee66b825b713611f89aa35d16de984f76f26c50982a25d52cd0910dff3923"}, + {file = "ruff-0.1.2-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f85f850a320ff532b8f93e8d1da6a36ef03698c446357c8c43b46ef90bb321eb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:809c6d4e45683696d19ca79e4c6bd3b2e9204fe9546923f2eb3b126ec314b0dc"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46005e4abb268e93cad065244e17e2ea16b6fcb55a5c473f34fbc1fd01ae34cb"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10cdb302f519664d5e2cf954562ac86c9d20ca05855e5b5c2f9d542228f45da4"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f89ebcbe57a1eab7d7b4ceb57ddf0af9ed13eae24e443a7c1dc078000bd8cc6b"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7344eaca057d4c32373c9c3a7afb7274f56040c225b6193dd495fcf69453b436"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dffa25f6e03c4950b6ac6f216bc0f98a4be9719cb0c5260c8e88d1bac36f1683"}, + {file = "ruff-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42ddaea52cb7ba7c785e8593a7532866c193bc774fe570f0e4b1ccedd95b83c5"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8533efda625bbec0bf27da2886bd641dae0c209104f6c39abc4be5b7b22de2a"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b0b1b82221ba7c50e03b7a86b983157b5d3f4d8d4f16728132bdf02c6d651f77"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c1362eb9288f8cc95535294cb03bd4665c8cef86ec32745476a4e5c6817034c"}, + {file = "ruff-0.1.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ffa7ef5ded0563329a35bd5a1cfdae40f05a75c0cc2dd30f00b1320b1fb461fc"}, + {file = "ruff-0.1.2-py3-none-win32.whl", hash = "sha256:6e8073f85e47072256e2e1909f1ae515cf61ff5a4d24730a63b8b4ac24b6704a"}, + {file = "ruff-0.1.2-py3-none-win_amd64.whl", hash = "sha256:b836ddff662a45385948ee0878b0a04c3a260949905ad861a37b931d6ee1c210"}, + {file = "ruff-0.1.2-py3-none-win_arm64.whl", hash = "sha256:b0c42d00db5639dbd5f7f9923c63648682dd197bf5de1151b595160c96172691"}, + {file = "ruff-0.1.2.tar.gz", hash = "sha256:afd4785ae060ce6edcd52436d0c197628a918d6d09e3107a892a1bad6a4c6608"}, +] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + +[[package]] +name = "types-python-slugify" +version = "8.0.0.3" +description = "Typing stubs for python-slugify" +optional = false +python-versions = "*" +files = [ + {file = "types-python-slugify-8.0.0.3.tar.gz", hash = "sha256:868e6610ab9a01c01b2ccc1b982363e694d6bbb4fcf32e0d82688c89dceb4e2c"}, + {file = "types_python_slugify-8.0.0.3-py3-none-any.whl", hash = "sha256:2353c161c79ab6cce955b50720c6cd03586ec297558122236d130e4a19f21209"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "7387371b3507348467a83780d62e7e3e0cf33bd0e6f8346c9cfa03e6e86a46ab" diff --git a/libs/hash-graph-types/python/poetry.toml b/libs/hash-graph-types/python/poetry.toml new file mode 100644 index 0000000..a5f04e6 --- /dev/null +++ b/libs/hash-graph-types/python/poetry.toml @@ -0,0 +1,3 @@ +[virtualenvs] +name = ".venv" +in-project = true diff --git a/libs/hash-graph-types/python/pyproject.toml b/libs/hash-graph-types/python/pyproject.toml new file mode 100644 index 0000000..4438efd --- /dev/null +++ b/libs/hash-graph-types/python/pyproject.toml @@ -0,0 +1,82 @@ +[tool.poetry] +name = "hash-graph-types" +version = "0.0.0" +description = "Type definitions for the type system and entity validation based on schemas" +license = "AGPL-3.0-only" +authors = ["HASH"] +readme = "README.md" +packages = [{ include = "graph_types" }] + +[tool.poetry.dependencies] +python = "^3.11" + +pydantic = "^2.4.2" +pydantic_core = "^2.10.1" +python-slugify = "^8.0.1" +types-python-slugify = "^8.0" + +[tool.poetry.group.dev.dependencies] +setuptools = "^68.2.2" + +[tool.poetry.group.lint-tools.dependencies] +black = "^23.10.1" +ruff = "^0.1.2" +mypy = "^1.6.1" + + +[tool.black] +target-version = ['py311'] +preview = true + +[tool.ruff] +select = ["ALL"] +ignore = [ + "D203", # this conflicts with `D211` + "D213", # this conflicts with `D212` + "D401", # Relates to PEP-257 but also conflicts with Google Python Style Guide, generally gets in the way + "ANN101", # most type checkers infer the type of `self` automatically + "ANN102", # most type checkers infer the type of `cls` automatically + "FIX002", # TODOs should be fixed, not removed + "TD002", # We don't add authors to TODO strings + "PLC0414", # Conflicts with `no_implicit_reexport = true` +] + +target-version = "py311" + +[tool.mypy] +plugins = "pydantic.mypy" + +disallow_untyped_defs = true +disallow_any_unimported = true +no_implicit_optional = true +check_untyped_defs = true +no_implicit_reexport = true +strict_optional = true +show_error_codes = true +show_traceback = true +strict_equality = true + +# warnings +warn_unused_configs = true +warn_return_any = true +warn_incomplete_stub = true +warn_unreachable = true +warn_redundant_casts = true +warn_unused_ignores = true + +# error messages +pretty = true +color_output = true +error_summary = true +incremental = true + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/libs/hash-graph-types/python/turbo.json b/libs/hash-graph-types/python/turbo.json new file mode 100644 index 0000000..8ff639a --- /dev/null +++ b/libs/hash-graph-types/python/turbo.json @@ -0,0 +1,41 @@ +{ + "extends": ["//"], + "pipeline": { + "build": { + "dependsOn": ["^build", "codegen"], + "inputs": ["./**/*.py", "pyproject.toml", "poetry.lock", "LICENSE*"], + "outputs": ["dist/**"] + }, + "poetry:venv": { + "cache": false + }, + "poetry:install": { + "cache": false + }, + "poetry:install-production": { + "cache": false + }, + "fix:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "fix:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"], + "outputs": ["poetry.lock"] + }, + "lint:black": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:lock-files": { + "inputs": ["poetry.lock", "pyproject.toml"] + }, + "lint:ruff": { + "inputs": ["./**/*.py", "pyproject.toml"] + }, + "lint:mypy": { + "inputs": ["./**/*.py", "pyproject.toml"] + } + } +}