From c47af85fd2211a7fce58739f60866dd0ae5cffc9 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:46:07 +0000 Subject: [PATCH] SDK regeneration --- poetry.lock | 6 +- pyproject.toml | 2 +- reference.md | 739 ++++++++---- src/sayari/__init__.py | 50 +- src/sayari/base_client.py | 12 + src/sayari/core/client_wrapper.py | 2 +- .../entity/types/entity_summary_response.py | 9 + .../entity/types/get_entity_response.py | 3 + src/sayari/notifications/client.py | 4 +- .../types/project_notification_data.py | 7 +- .../types/project_notifications_response.py | 130 ++- src/sayari/ontology/types/ontology_source.py | 4 +- src/sayari/project/__init__.py | 6 - src/sayari/project/client.py | 412 +------ src/sayari/project/types/__init__.py | 6 - src/sayari/project/types/bucket_agg.py | 2 - .../project/types/create_project_request.py | 7 +- .../project/types/create_project_response.py | 9 +- .../types/get_project_entities_response.py | 59 +- src/sayari/project/types/project.py | 3 +- .../project/types/project_entities_aggs.py | 7 +- .../project/types/project_entities_filter.py | 14 +- src/sayari/project_entity/__init__.py | 14 +- src/sayari/project_entity/client.py | 184 ++- src/sayari/project_entity/types/__init__.py | 14 +- .../types/attributes_response.py} | 9 +- .../types/grouped_attribute.py} | 10 +- .../types/grouped_attribute_value.py} | 10 +- .../project_entity/types/match_count.py | 5 + .../types/match_profile_enum.py | 5 + .../project_entity/types/match_result.py | 5 - .../types/project_entities_response.py | 116 +- .../types/project_entity_match_response.py | 5 +- .../types/project_entity_response.py | 13 +- .../types/project_risk_category.py | 21 + .../types/single_project_entity_response.py | 117 +- .../project_entity_attributes/__init__.py | 13 + .../project_entity_attributes/client.py | 310 +++++ .../types/__init__.py | 11 + ...update_project_entity_attribute_request.py | 33 + ...pdate_project_entity_attribute_response.py | 38 + ..._project_entity_attribute_response_data.py | 22 + .../__init__.py | 23 + .../client.py | 1014 +++++++++++++++++ .../types/__init__.py | 21 + ...ct_entity_supply_chain_snapshot_request.py | 31 + ...t_entity_supply_chain_snapshot_response.py | 31 + ...ty_supply_chain_snapshot_by_id_response.py | 109 ++ ...oject_entity_supply_chain_snapshot_data.py | 25 + ...ntity_supply_chain_snapshot_detail_data.py | 29 + ..._entity_supply_chain_snapshots_response.py | 43 + .../types/supply_chain_edge.py | 26 + .../types/supply_chain_node.py | 24 + .../search/types/entity_search_response.py | 1 + src/sayari/search/types/filter_list.py | 5 + src/sayari/shared_types/types/core_entity.py | 1 + .../shared_types/types/embedded_entity.py | 1 + src/sayari/supply_chain/client.py | 40 +- .../traversal/types/shortest_path_response.py | 2 + .../traversal/types/traversal_response.py | 2 + 60 files changed, 2927 insertions(+), 949 deletions(-) rename src/sayari/{project/types/hs_code_agg.py => project_entity/types/attributes_response.py} (78%) rename src/sayari/{project/types/hs_code_agg_terms.py => project_entity/types/grouped_attribute.py} (71%) rename src/sayari/{project/types/hs_code_agg_bucket.py => project_entity/types/grouped_attribute_value.py} (74%) create mode 100644 src/sayari/project_entity/types/match_count.py create mode 100644 src/sayari/project_entity/types/match_profile_enum.py delete mode 100644 src/sayari/project_entity/types/match_result.py create mode 100644 src/sayari/project_entity/types/project_risk_category.py create mode 100644 src/sayari/project_entity_attributes/__init__.py create mode 100644 src/sayari/project_entity_attributes/client.py create mode 100644 src/sayari/project_entity_attributes/types/__init__.py create mode 100644 src/sayari/project_entity_attributes/types/update_project_entity_attribute_request.py create mode 100644 src/sayari/project_entity_attributes/types/update_project_entity_attribute_response.py create mode 100644 src/sayari/project_entity_attributes/types/update_project_entity_attribute_response_data.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/__init__.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/client.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/__init__.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_request.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_response.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_by_id_response.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_data.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_detail_data.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshots_response.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_edge.py create mode 100644 src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_node.py diff --git a/poetry.lock b/poetry.lock index cea859e8..dfe67d2f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2025.6.15" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"}, - {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"}, + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index 0f52cf33..c9f17861 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "sayari" [tool.poetry] name = "sayari" -version = "0.1.42" +version = "0.1.43" description = "A Python SDK for Sayari" readme = "README.md" authors = [ diff --git a/reference.md b/reference.md index 77bfc4a7..a76be864 100644 --- a/reference.md +++ b/reference.md @@ -2643,6 +2643,463 @@ client.ontology.get_source_types( + + + + +## ProjectEntityAttributes +
client.project_entity_attributes.update_project_entity_attribute(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates a specific attribute for a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari +from sayari.project_entity_attributes import UpdateProjectEntityAttributeRequest + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity_attributes.update_project_entity_attribute( + project_id="V03eYM", + project_entity_id="BG72YW", + attribute_id="xG8wYP", + request=UpdateProjectEntityAttributeRequest( + field="name", + value="updated name", + match_resolution=True, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**attribute_id:** `str` + +
+
+ +
+
+ +**request:** `UpdateProjectEntityAttributeRequest` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## ProjectEntitySupplyChainSnapshots +
client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshots(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieves all supply chain snapshots for a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshots( + project_id="V03eYM", + project_entity_id="BG72YW", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshot_by_id(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieves a specific supply chain snapshot by ID for a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshot_by_id( + project_id="V03eYM", + project_entity_id="BG72YW", + snapshot_id="sN4p2K", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**snapshot_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.project_entity_supply_chain_snapshots.create_project_entity_supply_chain_snapshot(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Creates a new supply chain snapshot for a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari +from sayari.project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotRequest, +) + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity_supply_chain_snapshots.create_project_entity_supply_chain_snapshot( + project_id="V03eYM", + project_entity_id="BG72YW", + request=CreateProjectEntitySupplyChainSnapshotRequest( + label="Q1 2024 Supply Chain Analysis", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**request:** `CreateProjectEntitySupplyChainSnapshotRequest` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.project_entity_supply_chain_snapshots.delete_project_entity_supply_chain_snapshot_by_id(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Deletes a specific supply chain snapshot by ID for a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity_supply_chain_snapshots.delete_project_entity_supply_chain_snapshot_by_id( + project_id="project_id", + project_entity_id="project_entity_id", + snapshot_id="snapshot_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**snapshot_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -2683,13 +3140,13 @@ client = Sayari( client_secret="YOUR_CLIENT_SECRET", ) client.project_entity.create_project_entity( - project_id="YVB88Y", + project_id="0n4473", request=CreateResolvedProjectEntityRequest( - name=["VTB Bank"], - country=["RUS"], - address=["Moscow"], - identifier=["253400V1H6ART1UQ0N98"], - profile="corporate", + name=["Marvel Garment"], + country=["KHM"], + address=[ + "Beung Thom 3 Village, Sangkat Beung Thom, Posenchey, Phnom Penh" + ], ), ) @@ -2826,7 +3283,7 @@ client.project_entity.get_project_entities(
-**match_result:** `typing.Optional[typing.Sequence[MatchResult]]` — Filter by match result +**match_count:** `typing.Optional[MatchCount]` — Filter by match count
@@ -2834,7 +3291,7 @@ client.project_entity.get_project_entities(
-**match_strength_v_1:** `typing.Optional[typing.Sequence[MatchStrengthEnum]]` — Filter by match strength +**match_strength:** `typing.Optional[typing.Sequence[MatchStrengthEnum]]` — Filter by match strength
@@ -3066,7 +3523,7 @@ client.project_entity.get_project_entity(
-**match_result:** `typing.Optional[typing.Sequence[MatchResult]]` — Filter by match result +**match_count:** `typing.Optional[MatchCount]` — Filter by match count
@@ -3074,7 +3531,7 @@ client.project_entity.get_project_entity(
-**match_strength_v_1:** `typing.Optional[typing.Sequence[MatchStrengthEnum]]` — Filter by match strength +**match_strength:** `typing.Optional[typing.Sequence[MatchStrengthEnum]]` — Filter by match strength
@@ -3530,7 +3987,7 @@ client.project_entity.project_entity_supply_chain(
-**risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. +**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -3538,7 +3995,7 @@ client.project_entity.project_entity_supply_chain(
-**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors. +**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -3546,7 +4003,7 @@ client.project_entity.project_entity_supply_chain(
-**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries. +**risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors.
@@ -3554,7 +4011,7 @@ client.project_entity.project_entity_supply_chain(
-**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries. +**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors.
@@ -3562,7 +4019,7 @@ client.project_entity.project_entity_supply_chain(
-**shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from any tier matches the provided values. +**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries.
@@ -3570,7 +4027,7 @@ client.project_entity.project_entity_supply_chain(
-**not_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where none of the shipment countries from any tier matches the provided values. +**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries.
@@ -3578,7 +4035,7 @@ client.project_entity.project_entity_supply_chain(
-**tier_1_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 1 matches the provided values. +**shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from any tier matches the provided values.
@@ -3586,7 +4043,7 @@ client.project_entity.project_entity_supply_chain(
-**tier_2_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 2 matches the provided values. +**not_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where none of the shipment countries from any tier matches the provided values.
@@ -3594,7 +4051,7 @@ client.project_entity.project_entity_supply_chain(
-**tier_3_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 3 matches the provided values. +**tier_1_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 1 matches the provided values.
@@ -3602,7 +4059,7 @@ client.project_entity.project_entity_supply_chain(
-**tier_4_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 4 matches the provided values. +**tier_2_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 2 matches the provided values.
@@ -3610,7 +4067,7 @@ client.project_entity.project_entity_supply_chain(
-**tier_5_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. +**tier_3_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 3 matches the provided values.
@@ -3618,7 +4075,7 @@ client.project_entity.project_entity_supply_chain(
-**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. +**tier_4_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 4 matches the provided values.
@@ -3626,7 +4083,7 @@ client.project_entity.project_entity_supply_chain(
-**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. +**tier_5_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values.
@@ -3771,7 +4228,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**risk_factors:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. +**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -3779,7 +4236,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors. +**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -3787,7 +4244,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries. +**risk_factors:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors.
@@ -3795,7 +4252,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries. +**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors.
@@ -3803,7 +4260,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. +**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries.
@@ -3811,7 +4268,7 @@ client.project_entity.project_entity_supply_chain_summary(
-**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. +**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries.
@@ -3908,7 +4365,7 @@ Create a new project. ```python from sayari import Sayari -from sayari.project import CreateProjectRequest +from sayari.project import CreateProjectRequest, ProjectShareOnCreate client = Sayari( client_id="YOUR_CLIENT_ID", @@ -3916,7 +4373,10 @@ client = Sayari( ) client.project.create_project( request=CreateProjectRequest( - label="Project Alpha", + label="My First Project", + share=ProjectShareOnCreate( + org="admin", + ), ), ) @@ -4046,197 +4506,6 @@ client.project.get_projects( - - - - -
client.project.get_project_entities(...) -
-
- -#### 📝 Description - -
-
- -
-
- -This endpoint is deprecated. Retrieve a list of entities in a project. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from sayari import Sayari - -client = Sayari( - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", -) -client.project.get_project_entities( - id="gPq6EY", - accept="application/json", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**id:** `str` — The project identifier. - -
-
- -
-
- -**accept:** `GetProjectEntitiesAcceptHeader` — The response format. Defaults to application/json. - -
-
- -
-
- -**next:** `typing.Optional[str]` — The pagination token for the next page of entities. - -
-
- -
-
- -**prev:** `typing.Optional[str]` — The pagination token for the previous page of entities. - -
-
- -
-
- -**limit:** `typing.Optional[int]` — Limit total entities returned. Defaults to 1,000. Max 10,000. - -
-
- -
-
- -**entity_types:** `typing.Optional[typing.Union[Entities, typing.Sequence[Entities]]]` — Only return entities of the specified [entity type(s)](/sayari-library/ontology/entities). Defaults to all types. - -
-
- -
-
- -**geo_facets:** `typing.Optional[bool]` — Whether to include geo facets in the response. Defaults to false. - -
-
- -
-
- -**hs_codes:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return entities with the specified HS code(s) in their supply chain. - -
-
- -
-
- -**received_hs_codes:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return entities that received the specified HS code(s). - -
-
- -
-
- -**shipped_hs_codes:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return entities that shipped the specified HS code(s). - -
-
- -
-
- -**combined_hs_codes:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return entities that have shipped or received the specified HS code(s). - -
-
- -
-
- -**translation:** `typing.Optional[str]` — The language code to translate the entity labels to. Defaults to the user's preferred language. - -
-
- -
-
- -**sort:** `typing.Optional[SortField]` - -
-
- -
-
- -**filters:** `typing.Optional[ - typing.Union[ProjectEntitiesFilter, typing.Sequence[ProjectEntitiesFilter]] -]` — Filter for entities in a project. The format is `field=value`, where the equal sign is encoded as `%3D`. Supported fields are as follows - -
-
- -
-
- -**aggregations:** `typing.Optional[ - typing.Union[ - ProjectEntitiesAggsDefinition, - typing.Sequence[ProjectEntitiesAggsDefinition], - ] -]` — Aggregations that should be returned for entities in the project. - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- -
@@ -5738,7 +6007,7 @@ client.supply_chain.upstream_trade_traversal(
-**risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. +**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -5746,7 +6015,7 @@ client.supply_chain.upstream_trade_traversal(
-**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors. +**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product.
@@ -5754,7 +6023,7 @@ client.supply_chain.upstream_trade_traversal(
-**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries. +**risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors.
@@ -5762,7 +6031,7 @@ client.supply_chain.upstream_trade_traversal(
-**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries. +**not_risk:** `typing.Optional[typing.Sequence[Risk]]` — Risk leaf node filter. Only return supply chains that end with a supplier that has none of the specified risk factors.
@@ -5770,7 +6039,7 @@ client.supply_chain.upstream_trade_traversal(
-**shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from any tier matches the provided values. +**countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in 1+ of the specified countries.
@@ -5778,7 +6047,7 @@ client.supply_chain.upstream_trade_traversal(
-**not_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where none of the shipment countries from any tier matches the provided values. +**not_countries:** `typing.Optional[typing.Sequence[Country]]` — Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries.
@@ -5786,7 +6055,7 @@ client.supply_chain.upstream_trade_traversal(
-**tier_1_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 1 matches the provided values. +**shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from any tier matches the provided values.
@@ -5794,7 +6063,7 @@ client.supply_chain.upstream_trade_traversal(
-**tier_2_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 2 matches the provided values. +**not_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where none of the shipment countries from any tier matches the provided values.
@@ -5802,7 +6071,7 @@ client.supply_chain.upstream_trade_traversal(
-**tier_3_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 3 matches the provided values. +**tier_1_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 1 matches the provided values.
@@ -5810,7 +6079,7 @@ client.supply_chain.upstream_trade_traversal(
-**tier_4_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 4 matches the provided values. +**tier_2_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 2 matches the provided values.
@@ -5818,7 +6087,7 @@ client.supply_chain.upstream_trade_traversal(
-**tier_5_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. +**tier_3_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 3 matches the provided values.
@@ -5826,7 +6095,7 @@ client.supply_chain.upstream_trade_traversal(
-**product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. +**tier_4_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 4 matches the provided values.
@@ -5834,7 +6103,7 @@ client.supply_chain.upstream_trade_traversal(
-**not_product:** `typing.Optional[typing.Sequence[str]]` — Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. +**tier_5_shipment_country:** `typing.Optional[typing.Sequence[Country]]` — Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values.
diff --git a/src/sayari/__init__.py b/src/sayari/__init__.py index c71b0998..95532d56 100644 --- a/src/sayari/__init__.py +++ b/src/sayari/__init__.py @@ -13,6 +13,8 @@ ontology, project, project_entity, + project_entity_attributes, + project_entity_supply_chain_snapshots, record, resolution, resource, @@ -195,9 +197,6 @@ GetProjectEntitiesAcceptHeader, GetProjectEntitiesResponse, GetProjectsResponse, - HsCodeAgg, - HsCodeAggBucket, - HsCodeAggTerms, IntKeyValue, Project, ProjectCounts, @@ -224,14 +223,18 @@ AttributeType, AttributeTypesResponse, AttributeValues, + AttributesResponse, BusinessPurpose, CaseStatus, CountType, CreateResolvedProjectEntityRequest, FacetBucket, FacetsResponse, + GroupedAttribute, + GroupedAttributeValue, Location, - MatchResult, + MatchCount, + MatchProfileEnum, MatchStrengthEnum, MatchedAttributes, ProductBucket, @@ -245,6 +248,7 @@ ProjectEntitySupplyChainSummaryResponse, ProjectEntitySupplyChainSummaryResponseData, ProjectEntitySupplyChainUpstream, + ProjectRiskCategory, ProjectRiskFactor, ResolutionAttributes, ResolutionProfile, @@ -263,6 +267,21 @@ UpstreamCount, UpstreamInfo, ) +from .project_entity_attributes import ( + UpdateProjectEntityAttributeRequest, + UpdateProjectEntityAttributeResponse, + UpdateProjectEntityAttributeResponseData, +) +from .project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotRequest, + CreateProjectEntitySupplyChainSnapshotResponse, + ProjectEntitySupplyChainSnapshotByIdResponse, + ProjectEntitySupplyChainSnapshotData, + ProjectEntitySupplyChainSnapshotDetailData, + ProjectEntitySupplyChainSnapshotsResponse, + SupplyChainEdge, + SupplyChainNode, +) from .record import GetRecordResponse, RecordReferences from .resolution import ( MatchExplanation, @@ -407,6 +426,7 @@ "AttributeTypesResponse", "AttributeValues", "Attributes", + "AttributesResponse", "AuthResponse", "BadGateway", "BadGatewayResponse", @@ -443,6 +463,8 @@ "CountryData", "CountryInfo", "CountryProperties", + "CreateProjectEntitySupplyChainSnapshotRequest", + "CreateProjectEntitySupplyChainSnapshotResponse", "CreateProjectRequest", "CreateProjectResponse", "CreateResolvedProjectEntityRequest", @@ -507,12 +529,11 @@ "GetProjectsResponse", "GetRecordResponse", "GetSourceResponse", + "GroupedAttribute", + "GroupedAttributeValue", "HistoryInfo", "HistoryResponse", "HsCode", - "HsCodeAgg", - "HsCodeAggBucket", - "HsCodeAggTerms", "HsCodeInfo", "Identifier", "IdentifierData", @@ -525,9 +546,10 @@ "Language", "ListSourcesResponse", "Location", + "MatchCount", "MatchExplanation", + "MatchProfileEnum", "MatchQuality", - "MatchResult", "MatchStrength", "MatchStrengthEnum", "MatchedAttributes", @@ -610,6 +632,10 @@ "ProjectEntityIdResponse", "ProjectEntityMatchResponse", "ProjectEntityResponse", + "ProjectEntitySupplyChainSnapshotByIdResponse", + "ProjectEntitySupplyChainSnapshotData", + "ProjectEntitySupplyChainSnapshotDetailData", + "ProjectEntitySupplyChainSnapshotsResponse", "ProjectEntitySupplyChainSummaryResponse", "ProjectEntitySupplyChainSummaryResponseData", "ProjectEntitySupplyChainUpstream", @@ -617,6 +643,7 @@ "ProjectNotificationData", "ProjectNotificationRiskData", "ProjectNotificationsResponse", + "ProjectRiskCategory", "ProjectRiskFactor", "ProjectShareOnCreate", "ProjectWithMembers", @@ -703,6 +730,8 @@ "SupplierMetadata", "SupplierOrBuyer", "SupplierSearchResponse", + "SupplyChainEdge", + "SupplyChainNode", "Tag", "TagResponse", "TierCount", @@ -733,6 +762,9 @@ "Unit", "UpdateAttribute", "UpdateEntityTagsResponse", + "UpdateProjectEntityAttributeRequest", + "UpdateProjectEntityAttributeResponse", + "UpdateProjectEntityAttributeResponseData", "UpdateProjectEntityTagsBody", "UpstreamCount", "UpstreamInfo", @@ -759,6 +791,8 @@ "ontology", "project", "project_entity", + "project_entity_attributes", + "project_entity_supply_chain_snapshots", "record", "resolution", "resource", diff --git a/src/sayari/base_client.py b/src/sayari/base_client.py index eebacc17..f4f0ab9a 100644 --- a/src/sayari/base_client.py +++ b/src/sayari/base_client.py @@ -13,6 +13,8 @@ from .negative_news.client import NegativeNewsClient from .notifications.client import NotificationsClient from .ontology.client import OntologyClient +from .project_entity_attributes.client import ProjectEntityAttributesClient +from .project_entity_supply_chain_snapshots.client import ProjectEntitySupplyChainSnapshotsClient from .project_entity.client import ProjectEntityClient from .project.client import ProjectClient from .record.client import RecordClient @@ -32,6 +34,8 @@ from .negative_news.client import AsyncNegativeNewsClient from .notifications.client import AsyncNotificationsClient from .ontology.client import AsyncOntologyClient +from .project_entity_attributes.client import AsyncProjectEntityAttributesClient +from .project_entity_supply_chain_snapshots.client import AsyncProjectEntitySupplyChainSnapshotsClient from .project_entity.client import AsyncProjectEntityClient from .project.client import AsyncProjectClient from .record.client import AsyncRecordClient @@ -126,6 +130,10 @@ def __init__( self.negative_news = NegativeNewsClient(client_wrapper=self._client_wrapper) self.notifications = NotificationsClient(client_wrapper=self._client_wrapper) self.ontology = OntologyClient(client_wrapper=self._client_wrapper) + self.project_entity_attributes = ProjectEntityAttributesClient(client_wrapper=self._client_wrapper) + self.project_entity_supply_chain_snapshots = ProjectEntitySupplyChainSnapshotsClient( + client_wrapper=self._client_wrapper + ) self.project_entity = ProjectEntityClient(client_wrapper=self._client_wrapper) self.project = ProjectClient(client_wrapper=self._client_wrapper) self.record = RecordClient(client_wrapper=self._client_wrapper) @@ -220,6 +228,10 @@ def __init__( self.negative_news = AsyncNegativeNewsClient(client_wrapper=self._client_wrapper) self.notifications = AsyncNotificationsClient(client_wrapper=self._client_wrapper) self.ontology = AsyncOntologyClient(client_wrapper=self._client_wrapper) + self.project_entity_attributes = AsyncProjectEntityAttributesClient(client_wrapper=self._client_wrapper) + self.project_entity_supply_chain_snapshots = AsyncProjectEntitySupplyChainSnapshotsClient( + client_wrapper=self._client_wrapper + ) self.project_entity = AsyncProjectEntityClient(client_wrapper=self._client_wrapper) self.project = AsyncProjectClient(client_wrapper=self._client_wrapper) self.record = AsyncRecordClient(client_wrapper=self._client_wrapper) diff --git a/src/sayari/core/client_wrapper.py b/src/sayari/core/client_wrapper.py index 86784498..f5ae1103 100644 --- a/src/sayari/core/client_wrapper.py +++ b/src/sayari/core/client_wrapper.py @@ -22,7 +22,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "sayari", - "X-Fern-SDK-Version": "0.1.42", + "X-Fern-SDK-Version": "0.1.43", } token = self._get_token() if token is not None: diff --git a/src/sayari/entity/types/entity_summary_response.py b/src/sayari/entity/types/entity_summary_response.py index ca79218e..55389baa 100644 --- a/src/sayari/entity/types/entity_summary_response.py +++ b/src/sayari/entity/types/entity_summary_response.py @@ -179,6 +179,7 @@ class EntitySummaryResponse(EntityDetails): "address": 6, }, reference_id="ecdfb3f2ecc8c3797e77d5795a8066ef/06517802/1540252800000:4a34442eccf1622995130b194a5d50e7", + logistics_entity=False, attributes=AttributeDetails( name=NameInfo( offset=0, @@ -663,6 +664,7 @@ class EntitySummaryResponse(EntityDetails): "status": 1, }, reference_id="b9d809b02049993ba8dc2e4c5f7cceca/RM201601838935/1590327027286:74e256656669aa44a5671d4f8898917b", + logistics_entity=False, ), matches={}, ), @@ -744,6 +746,7 @@ class EntitySummaryResponse(EntityDetails): "address": 4, }, reference_id="b4d06d4b77f51fab3c77c9653aabdda4/a80e7f4c-c219-437b-9941-32d89ea5885a/1560542045043:15d813b260619393762864f22d3c5b2d", + logistics_entity=False, ), matches={}, ), @@ -821,6 +824,7 @@ class EntitySummaryResponse(EntityDetails): "address": 1, }, reference_id="b67ab545f3ddc960d272d11ec5952665/829099316/1591105044949:7d86f50bb976ee542fcfac7bd17b6cca", + logistics_entity=False, ), matches={}, ), @@ -888,6 +892,7 @@ class EntitySummaryResponse(EntityDetails): "status": 1, }, reference_id="985b4533cd1cb2db1d736dd31f8e34c9/January 2013.pdf/1643737587282:f1b8f7a9ed23af356dcd37ce6c3ea059", + logistics_entity=False, ), matches={}, ), @@ -937,6 +942,7 @@ class EntitySummaryResponse(EntityDetails): attribute_counts={"name": 1, "country": 2, "address": 1}, attribute_count={"name": 1, "country": 2, "address": 1}, reference_id="b9d809b02049993ba8dc2e4c5f7cceca/RM201601838933/1590326996292:e8a8042f374e3dc41f62621f66357db2", + logistics_entity=False, ), matches={}, ), @@ -994,6 +1000,7 @@ class EntitySummaryResponse(EntityDetails): "additional_information": 3, }, reference_id="b9d809b02049993ba8dc2e4c5f7cceca/RM200901021433/1589580993652:90376816c6039ba02628d4db100fc79f", + logistics_entity=False, ), matches={}, ), @@ -1058,6 +1065,7 @@ class EntitySummaryResponse(EntityDetails): "status": 1, }, reference_id="b9d809b02049993ba8dc2e4c5f7cceca/RM201601838934/1590327029874:8bbf00ad8adcb3f371a01e15dea7a1ff", + logistics_entity=False, ), matches={}, ), @@ -1097,6 +1105,7 @@ class EntitySummaryResponse(EntityDetails): attribute_counts={"name": 1, "country": 1}, attribute_count={"name": 1, "country": 1}, reference_id="542ad2352af9ce07202a2f34d402d5bf/UK00004079756/1723420800000:b2ae9158c53ea711278ce72cccb2c8b2", + logistics_entity=False, ), matches={}, ), diff --git a/src/sayari/entity/types/get_entity_response.py b/src/sayari/entity/types/get_entity_response.py index 012dbab7..a303ac36 100644 --- a/src/sayari/entity/types/get_entity_response.py +++ b/src/sayari/entity/types/get_entity_response.py @@ -171,6 +171,7 @@ class GetEntityResponse(EntityDetails): "address": 7, }, reference_id="ecdfb3f2ecc8c3797e77d5795a8066ef/06517802/1540252800000:4a34442eccf1622995130b194a5d50e7", + logistics_entity=False, attributes=AttributeDetails( additional_information=AdditionalInformationInfo( limit=1, @@ -433,6 +434,7 @@ class GetEntityResponse(EntityDetails): "address": 3, }, reference_id="ecdfb3f2ecc8c3797e77d5795a8066ef/11043864/1540252800000:40ec7b0310d308ebf9006148b53a2802", + logistics_entity=False, ), types={ "has_shareholder": [ @@ -564,6 +566,7 @@ class GetEntityResponse(EntityDetails): "address": 3, }, reference_id="b4d06d4b77f51fab3c77c9653aabdda4/a80e7f4c-c219-437b-9941-32d89ea5885a/1560542045043:15d813b260619393762864f22d3c5b2d", + logistics_entity=False, ), editable=False, matches={}, diff --git a/src/sayari/notifications/client.py b/src/sayari/notifications/client.py index cfd72ec8..28b85819 100644 --- a/src/sayari/notifications/client.py +++ b/src/sayari/notifications/client.py @@ -74,7 +74,7 @@ def project_notifications( client_secret="YOUR_CLIENT_SECRET", ) client.notifications.project_notifications( - id="0oZnoG", + id="0dLeO0", limit=20, ) """ @@ -684,7 +684,7 @@ async def project_notifications( async def main() -> None: await client.notifications.project_notifications( - id="0oZnoG", + id="0dLeO0", limit=20, ) diff --git a/src/sayari/notifications/types/project_notification_data.py b/src/sayari/notifications/types/project_notification_data.py index db70251c..0f382f56 100644 --- a/src/sayari/notifications/types/project_notification_data.py +++ b/src/sayari/notifications/types/project_notification_data.py @@ -9,11 +9,6 @@ class ProjectNotificationData(UniversalBaseModel): - id: str = pydantic.Field() - """ - The ID of the entity - """ - resource_id: str = pydantic.Field() """ The ID of the saved resource @@ -25,7 +20,7 @@ class ProjectNotificationData(UniversalBaseModel): """ notifications: typing.List[Notification] - custom_fields: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) + custom_fields: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) """ This property is in beta and is subject to change. It is provided for early access and testing purposes only. custom user key/value pairs (key must be prefixed with "custom_" and value must be "string" type) """ diff --git a/src/sayari/notifications/types/project_notifications_response.py b/src/sayari/notifications/types/project_notifications_response.py index 0d369dca..d52eab33 100644 --- a/src/sayari/notifications/types/project_notifications_response.py +++ b/src/sayari/notifications/types/project_notifications_response.py @@ -23,95 +23,139 @@ class ProjectNotificationsResponse(UniversalBaseModel): ) ProjectNotificationsResponse( - offset=0, - limit=20, next=False, size=QualifiedCount( - count=3, + count=73, qualifier="eq", ), data=[ ProjectNotificationData( - id="dlOL1cZzEkIEZcRUcrBZCQ", - entity_id="dlOL1cZzEkIEZcRUcrBZCQ", - resource_id="0eZQ43", + resource_id="olxQPZ", + entity_id="IoKwj2-82wwzZRlFA1htGQ", notifications=[ + Notification( + type="risk", + field="exports_ilab_child_labor", + values=["false"], + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="exports_ilab_forced_labor", + values=["false"], + date="2025-06-04T00:00:00.000Z", + ), Notification( type="risk", field="forced_labor_xinjiang_origin_subtier", + values=["3"], + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="psa_exports_ilab_child_labor", values=["false"], - date="2024-02-06T00:00:00.000Z", - ) + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="psa_exports_ilab_forced_labor", + values=["false"], + date="2025-06-04T00:00:00.000Z", + ), ], - custom_fields={"properties": {"custom_name": "Victoria Beckham"}}, + custom_fields={}, risk_notifications=ProjectNotificationRiskData( - added=["forced_labor_xinjiang_origin_subtier"], - removed=[], - date="2024-02-06T00:00:00.000Z", + added=[ + "exports_ilab_child_labor", + "exports_ilab_forced_labor", + "psa_exports_ilab_child_labor", + "psa_exports_ilab_forced_labor", + ], + removed=["forced_labor_xinjiang_origin_subtier"], + date="2025-06-04T00:00:00.000Z", ), ), ProjectNotificationData( - id="wxwqZshCF4trlrmOa2eu9w", - entity_id="wxwqZshCF4trlrmOa2eu9w", - resource_id="03ePyj", + resource_id="Kx1w34", + entity_id="3oKp0fp1UE-W8BG5crAFIw", notifications=[ Notification( type="risk", - field="forced_labor_sheffield_hallam_university_reports_origin_subtier", - values=["3"], - date="2024-02-15T00:00:00.000Z", - ) + field="exports_ilab_child_labor", + values=["true"], + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="exports_ilab_forced_labor", + values=["true"], + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="psa_exports_ilab_child_labor", + values=["true"], + date="2025-06-04T00:00:00.000Z", + ), + Notification( + type="risk", + field="psa_exports_ilab_forced_labor", + values=["true"], + date="2025-06-04T00:00:00.000Z", + ), ], + custom_fields={}, risk_notifications=ProjectNotificationRiskData( added=[], removed=[ - "forced_labor_sheffield_hallam_university_reports_origin_subtier" + "exports_ilab_child_labor", + "exports_ilab_forced_labor", + "psa_exports_ilab_child_labor", + "psa_exports_ilab_forced_labor", ], - date="2024-02-15T00:00:00.000Z", + date="2025-06-04T00:00:00.000Z", ), ), ProjectNotificationData( - id="dX9cfM3FPefIp8VAuBKgIQ", - entity_id="dX9cfM3FPefIp8VAuBKgIQ", - resource_id="0XEQaX", + resource_id="BOMrB9", + entity_id="PF0ehzmptuJ2VJr2J5u0nw", notifications=[ Notification( type="risk", - field="owner_of_regulatory_action_entity", - values=["1"], - date="2024-02-06T00:00:00.000Z", - ), - Notification( - type="risk", - field="forced_labor_sheffield_hallam_university_reports_origin_direct", - values=["1"], - date="2024-02-15T00:00:00.000Z", + field="export_controls_adjacent", + values=["true"], + date="2025-06-14T00:00:00.000Z", ), Notification( type="risk", - field="forced_labor_sheffield_hallam_university_reports_origin_subtier", - values=["false"], - date="2024-02-15T00:00:00.000Z", + field="exports_bis_high_priority_items_critical_components_indirect", + values=["3"], + date="2025-06-14T00:00:00.000Z", ), ], - custom_fields={"properties": {"custom_identifier": "abc123"}}, + custom_fields={}, risk_notifications=ProjectNotificationRiskData( added=[ - "forced_labor_sheffield_hallam_university_reports_origin_subtier" + "exports_ilab_child_labor", + "exports_ilab_forced_labor", + "psa_exports_ilab_child_labor", + "psa_exports_ilab_forced_labor", ], removed=[ - "owner_of_regulatory_action_entity", - "forced_labor_sheffield_hallam_university_reports_origin_direct", + "export_controls_adjacent", + "exports_bis_high_priority_items_critical_components_indirect", + "psa_exports_bis_high_priority_items_critical_components_indirect", + "psa_forced_labor_uflpa_origin_subtier", + "psa_regulatory_action", ], - date="2024-02-15T00:00:00.000Z", + date="2025-06-04T00:00:00.000Z", ), ), ], ) """ - offset: int - limit: int next: bool data: typing.List[ProjectNotificationData] size: QualifiedCount diff --git a/src/sayari/ontology/types/ontology_source.py b/src/sayari/ontology/types/ontology_source.py index 26881a8e..3ed6ea02 100644 --- a/src/sayari/ontology/types/ontology_source.py +++ b/src/sayari/ontology/types/ontology_source.py @@ -4,8 +4,8 @@ from ...generated_types.types.country import Country import datetime as dt import pydantic -from ...core.pydantic_utilities import IS_PYDANTIC_V2 import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 class OntologySource(UniversalBaseModel): @@ -22,7 +22,7 @@ class OntologySource(UniversalBaseModel): source_type: str record_type: str structure: str - source_url: str + source_url: typing.Optional[str] = None pep: bool watchlist: bool diff --git a/src/sayari/project/__init__.py b/src/sayari/project/__init__.py index efc4181c..b9acab6e 100644 --- a/src/sayari/project/__init__.py +++ b/src/sayari/project/__init__.py @@ -9,9 +9,6 @@ GetProjectEntitiesAcceptHeader, GetProjectEntitiesResponse, GetProjectsResponse, - HsCodeAgg, - HsCodeAggBucket, - HsCodeAggTerms, IntKeyValue, Project, ProjectCounts, @@ -43,9 +40,6 @@ "GetProjectEntitiesAcceptHeader", "GetProjectEntitiesResponse", "GetProjectsResponse", - "HsCodeAgg", - "HsCodeAggBucket", - "HsCodeAggTerms", "IntKeyValue", "Project", "ProjectCounts", diff --git a/src/sayari/project/client.py b/src/sayari/project/client.py index 2f68712a..6962d3d7 100644 --- a/src/sayari/project/client.py +++ b/src/sayari/project/client.py @@ -22,16 +22,8 @@ from json.decoder import JSONDecodeError from ..core.api_error import ApiError from .types.get_projects_response import GetProjectsResponse -from .types.get_project_entities_accept_header import GetProjectEntitiesAcceptHeader -from ..generated_types.types.entities import Entities -from .types.sort_field import SortField -from .types.project_entities_filter import ProjectEntitiesFilter -from .types.project_entities_aggs_definition import ProjectEntitiesAggsDefinition -from .types.get_project_entities_response import GetProjectEntitiesResponse -from ..core.jsonable_encoder import jsonable_encoder -from ..shared_errors.errors.not_acceptable import NotAcceptable -from ..shared_errors.types.not_acceptable_response import NotAcceptableResponse from .types.delete_project_response import DeleteProjectResponse +from ..core.jsonable_encoder import jsonable_encoder from ..core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters @@ -62,7 +54,7 @@ def create_project( Examples -------- from sayari import Sayari - from sayari.project import CreateProjectRequest + from sayari.project import CreateProjectRequest, ProjectShareOnCreate client = Sayari( client_id="YOUR_CLIENT_ID", @@ -70,7 +62,10 @@ def create_project( ) client.project.create_project( request=CreateProjectRequest( - label="Project Alpha", + label="My First Project", + share=ProjectShareOnCreate( + org="admin", + ), ), ) """ @@ -288,196 +283,6 @@ def get_projects( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def get_project_entities( - self, - id: str, - *, - accept: GetProjectEntitiesAcceptHeader, - next: typing.Optional[str] = None, - prev: typing.Optional[str] = None, - limit: typing.Optional[int] = None, - entity_types: typing.Optional[typing.Union[Entities, typing.Sequence[Entities]]] = None, - geo_facets: typing.Optional[bool] = None, - hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - received_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - shipped_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - combined_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - translation: typing.Optional[str] = None, - sort: typing.Optional[SortField] = None, - filters: typing.Optional[typing.Union[ProjectEntitiesFilter, typing.Sequence[ProjectEntitiesFilter]]] = None, - aggregations: typing.Optional[ - typing.Union[ProjectEntitiesAggsDefinition, typing.Sequence[ProjectEntitiesAggsDefinition]] - ] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> GetProjectEntitiesResponse: - """ - This endpoint is deprecated. Retrieve a list of entities in a project. - - Parameters - ---------- - id : str - The project identifier. - - accept : GetProjectEntitiesAcceptHeader - The response format. Defaults to application/json. - - next : typing.Optional[str] - The pagination token for the next page of entities. - - prev : typing.Optional[str] - The pagination token for the previous page of entities. - - limit : typing.Optional[int] - Limit total entities returned. Defaults to 1,000. Max 10,000. - - entity_types : typing.Optional[typing.Union[Entities, typing.Sequence[Entities]]] - Only return entities of the specified [entity type(s)](/sayari-library/ontology/entities). Defaults to all types. - - geo_facets : typing.Optional[bool] - Whether to include geo facets in the response. Defaults to false. - - hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities with the specified HS code(s) in their supply chain. - - received_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that received the specified HS code(s). - - shipped_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that shipped the specified HS code(s). - - combined_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that have shipped or received the specified HS code(s). - - translation : typing.Optional[str] - The language code to translate the entity labels to. Defaults to the user's preferred language. - - sort : typing.Optional[SortField] - - filters : typing.Optional[typing.Union[ProjectEntitiesFilter, typing.Sequence[ProjectEntitiesFilter]]] - Filter for entities in a project. The format is `field=value`, where the equal sign is encoded as `%3D`. Supported fields are as follows - - aggregations : typing.Optional[typing.Union[ProjectEntitiesAggsDefinition, typing.Sequence[ProjectEntitiesAggsDefinition]]] - Aggregations that should be returned for entities in the project. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - GetProjectEntitiesResponse - - Examples - -------- - from sayari import Sayari - - client = Sayari( - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - client.project.get_project_entities( - id="gPq6EY", - accept="application/json", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(id)}/contents/entity", - method="GET", - params={ - "next": next, - "prev": prev, - "limit": limit, - "entity_types": entity_types, - "geo_facets": geo_facets, - "hs_codes": hs_codes, - "received_hs_codes": received_hs_codes, - "shipped_hs_codes": shipped_hs_codes, - "combined_hs_codes": combined_hs_codes, - "translation": translation, - "sort": sort, - "filters": convert_and_respect_annotation_metadata( - object_=filters, annotation=ProjectEntitiesFilter, direction="write" - ), - "aggregations": aggregations, - }, - headers={ - "Accept": str(accept) if accept is not None else None, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - GetProjectEntitiesResponse, - parse_obj_as( - type_=GetProjectEntitiesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequest( - typing.cast( - BadRequestResponse, - parse_obj_as( - type_=BadRequestResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise Unauthorized( - typing.cast( - UnauthorizedResponse, - parse_obj_as( - type_=UnauthorizedResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 405: - raise MethodNotAllowed( - typing.cast( - MethodNotAllowedResponse, - parse_obj_as( - type_=MethodNotAllowedResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 406: - raise NotAcceptable( - typing.cast( - NotAcceptableResponse, - parse_obj_as( - type_=NotAcceptableResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise RateLimitExceeded( - typing.cast( - RateLimitResponse, - parse_obj_as( - type_=RateLimitResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - InternalServerErrorResponse, - parse_obj_as( - type_=InternalServerErrorResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - def delete_project( self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> DeleteProjectResponse: @@ -613,7 +418,7 @@ async def create_project( import asyncio from sayari import AsyncSayari - from sayari.project import CreateProjectRequest + from sayari.project import CreateProjectRequest, ProjectShareOnCreate client = AsyncSayari( client_id="YOUR_CLIENT_ID", @@ -624,7 +429,10 @@ async def create_project( async def main() -> None: await client.project.create_project( request=CreateProjectRequest( - label="Project Alpha", + label="My First Project", + share=ProjectShareOnCreate( + org="admin", + ), ), ) @@ -853,204 +661,6 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def get_project_entities( - self, - id: str, - *, - accept: GetProjectEntitiesAcceptHeader, - next: typing.Optional[str] = None, - prev: typing.Optional[str] = None, - limit: typing.Optional[int] = None, - entity_types: typing.Optional[typing.Union[Entities, typing.Sequence[Entities]]] = None, - geo_facets: typing.Optional[bool] = None, - hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - received_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - shipped_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - combined_hs_codes: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, - translation: typing.Optional[str] = None, - sort: typing.Optional[SortField] = None, - filters: typing.Optional[typing.Union[ProjectEntitiesFilter, typing.Sequence[ProjectEntitiesFilter]]] = None, - aggregations: typing.Optional[ - typing.Union[ProjectEntitiesAggsDefinition, typing.Sequence[ProjectEntitiesAggsDefinition]] - ] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> GetProjectEntitiesResponse: - """ - This endpoint is deprecated. Retrieve a list of entities in a project. - - Parameters - ---------- - id : str - The project identifier. - - accept : GetProjectEntitiesAcceptHeader - The response format. Defaults to application/json. - - next : typing.Optional[str] - The pagination token for the next page of entities. - - prev : typing.Optional[str] - The pagination token for the previous page of entities. - - limit : typing.Optional[int] - Limit total entities returned. Defaults to 1,000. Max 10,000. - - entity_types : typing.Optional[typing.Union[Entities, typing.Sequence[Entities]]] - Only return entities of the specified [entity type(s)](/sayari-library/ontology/entities). Defaults to all types. - - geo_facets : typing.Optional[bool] - Whether to include geo facets in the response. Defaults to false. - - hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities with the specified HS code(s) in their supply chain. - - received_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that received the specified HS code(s). - - shipped_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that shipped the specified HS code(s). - - combined_hs_codes : typing.Optional[typing.Union[str, typing.Sequence[str]]] - Only return entities that have shipped or received the specified HS code(s). - - translation : typing.Optional[str] - The language code to translate the entity labels to. Defaults to the user's preferred language. - - sort : typing.Optional[SortField] - - filters : typing.Optional[typing.Union[ProjectEntitiesFilter, typing.Sequence[ProjectEntitiesFilter]]] - Filter for entities in a project. The format is `field=value`, where the equal sign is encoded as `%3D`. Supported fields are as follows - - aggregations : typing.Optional[typing.Union[ProjectEntitiesAggsDefinition, typing.Sequence[ProjectEntitiesAggsDefinition]]] - Aggregations that should be returned for entities in the project. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - GetProjectEntitiesResponse - - Examples - -------- - import asyncio - - from sayari import AsyncSayari - - client = AsyncSayari( - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.project.get_project_entities( - id="gPq6EY", - accept="application/json", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/projects/{jsonable_encoder(id)}/contents/entity", - method="GET", - params={ - "next": next, - "prev": prev, - "limit": limit, - "entity_types": entity_types, - "geo_facets": geo_facets, - "hs_codes": hs_codes, - "received_hs_codes": received_hs_codes, - "shipped_hs_codes": shipped_hs_codes, - "combined_hs_codes": combined_hs_codes, - "translation": translation, - "sort": sort, - "filters": convert_and_respect_annotation_metadata( - object_=filters, annotation=ProjectEntitiesFilter, direction="write" - ), - "aggregations": aggregations, - }, - headers={ - "Accept": str(accept) if accept is not None else None, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - GetProjectEntitiesResponse, - parse_obj_as( - type_=GetProjectEntitiesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequest( - typing.cast( - BadRequestResponse, - parse_obj_as( - type_=BadRequestResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise Unauthorized( - typing.cast( - UnauthorizedResponse, - parse_obj_as( - type_=UnauthorizedResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 405: - raise MethodNotAllowed( - typing.cast( - MethodNotAllowedResponse, - parse_obj_as( - type_=MethodNotAllowedResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 406: - raise NotAcceptable( - typing.cast( - NotAcceptableResponse, - parse_obj_as( - type_=NotAcceptableResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise RateLimitExceeded( - typing.cast( - RateLimitResponse, - parse_obj_as( - type_=RateLimitResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - InternalServerErrorResponse, - parse_obj_as( - type_=InternalServerErrorResponse, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - async def delete_project( self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> DeleteProjectResponse: diff --git a/src/sayari/project/types/__init__.py b/src/sayari/project/types/__init__.py index 7e7758a6..069aeaa3 100644 --- a/src/sayari/project/types/__init__.py +++ b/src/sayari/project/types/__init__.py @@ -8,9 +8,6 @@ from .get_project_entities_accept_header import GetProjectEntitiesAcceptHeader from .get_project_entities_response import GetProjectEntitiesResponse from .get_projects_response import GetProjectsResponse -from .hs_code_agg import HsCodeAgg -from .hs_code_agg_bucket import HsCodeAggBucket -from .hs_code_agg_terms import HsCodeAggTerms from .int_key_value import IntKeyValue from .project import Project from .project_counts import ProjectCounts @@ -41,9 +38,6 @@ "GetProjectEntitiesAcceptHeader", "GetProjectEntitiesResponse", "GetProjectsResponse", - "HsCodeAgg", - "HsCodeAggBucket", - "HsCodeAggTerms", "IntKeyValue", "Project", "ProjectCounts", diff --git a/src/sayari/project/types/bucket_agg.py b/src/sayari/project/types/bucket_agg.py index 7ec68f19..8bd37aff 100644 --- a/src/sayari/project/types/bucket_agg.py +++ b/src/sayari/project/types/bucket_agg.py @@ -2,7 +2,6 @@ from ...core.pydantic_utilities import UniversalBaseModel import typing -from .int_key_value import IntKeyValue from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -16,7 +15,6 @@ class BucketAgg(UniversalBaseModel): doc_count: int label: typing.Optional[str] = None comment: typing.Optional[str] = None - hs_code_sums: typing.Optional[IntKeyValue] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project/types/create_project_request.py b/src/sayari/project/types/create_project_request.py index f12c8c80..a35ec56e 100644 --- a/src/sayari/project/types/create_project_request.py +++ b/src/sayari/project/types/create_project_request.py @@ -11,10 +11,13 @@ class CreateProjectRequest(UniversalBaseModel): """ Examples -------- - from sayari.project import CreateProjectRequest + from sayari.project import CreateProjectRequest, ProjectShareOnCreate CreateProjectRequest( - label="Project Alpha", + label="My First Project", + share=ProjectShareOnCreate( + org="admin", + ), ) """ diff --git a/src/sayari/project/types/create_project_response.py b/src/sayari/project/types/create_project_response.py index 6667dca8..8ba9371f 100644 --- a/src/sayari/project/types/create_project_response.py +++ b/src/sayari/project/types/create_project_response.py @@ -15,17 +15,18 @@ class CreateProjectResponse(UniversalBaseModel): CreateProjectResponse( data=Project( - id="YVMBRg", - label="Project Alpha", + id="0pjjaB", + label="My First Project", archived=False, - created="2024-03-15 20:31:06.08855+00", - updated="2024-03-15 20:31:06.08855+00", + created="2025-08-26 03:17:58.70405+00", + updated="2025-08-26 03:17:58.70405+00", counts=ProjectCounts( entity=0, graph=0, record=0, search=0, ), + is_scrm=False, ), ) """ diff --git a/src/sayari/project/types/get_project_entities_response.py b/src/sayari/project/types/get_project_entities_response.py index b16974dc..a6fc46ba 100644 --- a/src/sayari/project/types/get_project_entities_response.py +++ b/src/sayari/project/types/get_project_entities_response.py @@ -16,9 +16,6 @@ class GetProjectEntitiesResponse(PaginatedResponse): from sayari.project import ( BucketAgg, GetProjectEntitiesResponse, - HsCodeAgg, - HsCodeAggBucket, - HsCodeAggTerms, IntKeyValue, ProjectEntitiesAggs, ProjectEntity, @@ -321,29 +318,7 @@ class GetProjectEntitiesResponse(PaginatedResponse): doc_count=3, ), ], - received_hs_codes=HsCodeAgg( - doc_count=2, - hs_code_terms=HsCodeAggTerms( - doc_count_error_upper_bound=0, - sum_other_doc_count=0, - buckets=[ - HsCodeAggBucket( - key="271290", - doc_count=1, - hs_code_sums=IntKeyValue( - value=4, - ), - ), - HsCodeAggBucket( - key="271220", - doc_count=1, - hs_code_sums=IntKeyValue( - value=1, - ), - ), - ], - ), - ), + received_hs_codes=["271290", "271220"], custom_fields=[ BucketAgg( key="custom_id1", @@ -371,37 +346,7 @@ class GetProjectEntitiesResponse(PaginatedResponse): "eu_high_risk_third": {"tier4": 1}, "export_to_soe": {"tier1": 1, "tier3": 1, "tier4": 2}, }, - shipped_hs_codes=HsCodeAgg( - doc_count=0, - hs_code_terms=HsCodeAggTerms( - doc_count_error_upper_bound=0, - sum_other_doc_count=0, - buckets=[], - ), - ), - combined_hs_codes=HsCodeAgg( - doc_count=2, - hs_code_terms=HsCodeAggTerms( - doc_count_error_upper_bound=0, - sum_other_doc_count=0, - buckets=[ - HsCodeAggBucket( - key="271290", - doc_count=1, - hs_code_sums=IntKeyValue( - value=4, - ), - ), - HsCodeAggBucket( - key="271220", - doc_count=1, - hs_code_sums=IntKeyValue( - value=1, - ), - ), - ], - ), - ), + combined_hs_codes=["271290", "271220"], ), ) """ diff --git a/src/sayari/project/types/project.py b/src/sayari/project/types/project.py index 1ee4a2a7..55dc9eaf 100644 --- a/src/sayari/project/types/project.py +++ b/src/sayari/project/types/project.py @@ -3,8 +3,8 @@ from ...core.pydantic_utilities import UniversalBaseModel import pydantic from .project_counts import ProjectCounts -from ...core.pydantic_utilities import IS_PYDANTIC_V2 import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 class Project(UniversalBaseModel): @@ -26,6 +26,7 @@ class Project(UniversalBaseModel): created: str updated: str counts: ProjectCounts + is_scrm: typing.Optional[bool] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project/types/project_entities_aggs.py b/src/sayari/project/types/project_entities_aggs.py index 1da4ee28..cb231c2d 100644 --- a/src/sayari/project/types/project_entities_aggs.py +++ b/src/sayari/project/types/project_entities_aggs.py @@ -4,7 +4,6 @@ import typing from .bucket_agg import BucketAgg from .tier_count_agg import TierCountAgg -from .hs_code_agg import HsCodeAgg from .int_key_value import IntKeyValue from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -27,9 +26,9 @@ class ProjectEntitiesAggs(UniversalBaseModel): tag_ids: typing.Optional[typing.List[BucketAgg]] = None case_statuses: typing.Optional[typing.List[BucketAgg]] = None shipment_counts: typing.Optional[typing.List[BucketAgg]] = None - shipped_hs_codes: typing.Optional[HsCodeAgg] = None - received_hs_codes: typing.Optional[HsCodeAgg] = None - combined_hs_codes: typing.Optional[HsCodeAgg] = None + shipped_hs_codes: typing.Optional[typing.List[str]] = None + received_hs_codes: typing.Optional[typing.List[str]] = None + combined_hs_codes: typing.Optional[typing.List[str]] = None match_results: typing.Optional[typing.List[BucketAgg]] = None custom_fields: typing.Optional[typing.List[BucketAgg]] = None custom_fields_count: typing.Optional[IntKeyValue] = None diff --git a/src/sayari/project/types/project_entities_filter.py b/src/sayari/project/types/project_entities_filter.py index d8cb726b..5fd228a6 100644 --- a/src/sayari/project/types/project_entities_filter.py +++ b/src/sayari/project/types/project_entities_filter.py @@ -49,13 +49,6 @@ class ProjectEntitiesFilter(UniversalBaseModel): Filter by upstream (supply chain) [country](/sayari-library/ontology/enumerated-types#country) at any tier. """ - tier_0_shipment_country: typing_extensions.Annotated[ - typing.Optional[typing.List[Country]], FieldMetadata(alias="tier0_shipment_country") - ] = pydantic.Field(default=None) - """ - Filter by [country](/sayari-library/ontology/enumerated-types#country) at tier 0. - """ - tier_1_shipment_country: typing_extensions.Annotated[ typing.Optional[typing.List[Country]], FieldMetadata(alias="tier1_shipment_country") ] = pydantic.Field(default=None) @@ -84,6 +77,13 @@ class ProjectEntitiesFilter(UniversalBaseModel): Filter by upstream (supply chain) [country](/sayari-library/ontology/enumerated-types#country) at tier 4. """ + tier_5_shipment_country: typing_extensions.Annotated[ + typing.Optional[typing.List[Country]], FieldMetadata(alias="tier5_shipment_country") + ] = pydantic.Field(default=None) + """ + Filter by upstream (supply chain) [country](/sayari-library/ontology/enumerated-types#country) at tier 5. + """ + business_purpose: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ Filter by HS code, HS code description, or business description. diff --git a/src/sayari/project_entity/__init__.py b/src/sayari/project_entity/__init__.py index 82f696dc..add92aca 100644 --- a/src/sayari/project_entity/__init__.py +++ b/src/sayari/project_entity/__init__.py @@ -5,14 +5,18 @@ AttributeType, AttributeTypesResponse, AttributeValues, + AttributesResponse, BusinessPurpose, CaseStatus, CountType, CreateResolvedProjectEntityRequest, FacetBucket, FacetsResponse, + GroupedAttribute, + GroupedAttributeValue, Location, - MatchResult, + MatchCount, + MatchProfileEnum, MatchStrengthEnum, MatchedAttributes, ProductBucket, @@ -26,6 +30,7 @@ ProjectEntitySupplyChainSummaryResponse, ProjectEntitySupplyChainSummaryResponseData, ProjectEntitySupplyChainUpstream, + ProjectRiskCategory, ProjectRiskFactor, ResolutionAttributes, ResolutionProfile, @@ -50,14 +55,18 @@ "AttributeType", "AttributeTypesResponse", "AttributeValues", + "AttributesResponse", "BusinessPurpose", "CaseStatus", "CountType", "CreateResolvedProjectEntityRequest", "FacetBucket", "FacetsResponse", + "GroupedAttribute", + "GroupedAttributeValue", "Location", - "MatchResult", + "MatchCount", + "MatchProfileEnum", "MatchStrengthEnum", "MatchedAttributes", "ProductBucket", @@ -71,6 +80,7 @@ "ProjectEntitySupplyChainSummaryResponse", "ProjectEntitySupplyChainSummaryResponseData", "ProjectEntitySupplyChainUpstream", + "ProjectRiskCategory", "ProjectRiskFactor", "ResolutionAttributes", "ResolutionProfile", diff --git a/src/sayari/project_entity/client.py b/src/sayari/project_entity/client.py index 975b9423..83281508 100644 --- a/src/sayari/project_entity/client.py +++ b/src/sayari/project_entity/client.py @@ -23,7 +23,7 @@ from json.decoder import JSONDecodeError from ..core.api_error import ApiError from .types.case_status import CaseStatus -from .types.match_result import MatchResult +from .types.match_count import MatchCount from .types.match_strength_enum import MatchStrengthEnum from ..generated_types.types.risk import Risk from ..generated_types.types.risk_category import RiskCategory @@ -178,8 +178,8 @@ def get_project_entities( uploads: typing.Optional[typing.Sequence[str]] = None, case_status: typing.Optional[typing.Sequence[CaseStatus]] = None, tags: typing.Optional[typing.Sequence[str]] = None, - match_result: typing.Optional[typing.Sequence[MatchResult]] = None, - match_strength_v_1: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, + match_count: typing.Optional[MatchCount] = None, + match_strength: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, entity_types: typing.Optional[typing.Sequence[str]] = None, geo_facets: typing.Optional[bool] = None, exact_match: typing.Optional[bool] = None, @@ -215,10 +215,10 @@ def get_project_entities( tags : typing.Optional[typing.Sequence[str]] Filter by tag IDs - match_result : typing.Optional[typing.Sequence[MatchResult]] - Filter by match result + match_count : typing.Optional[MatchCount] + Filter by match count - match_strength_v_1 : typing.Optional[typing.Sequence[MatchStrengthEnum]] + match_strength : typing.Optional[typing.Sequence[MatchStrengthEnum]] Filter by match strength entity_types : typing.Optional[typing.Sequence[str]] @@ -290,8 +290,8 @@ def get_project_entities( "uploads": uploads, "case_status": case_status, "tags": tags, - "match_result": match_result, - "match_strength_v1": match_strength_v_1, + "match_count": match_count, + "match_strength": match_strength, "entity_types": entity_types, "geo_facets": geo_facets, "exact_match": exact_match, @@ -392,8 +392,8 @@ def get_project_entity( uploads: typing.Optional[typing.Sequence[str]] = None, case_status: typing.Optional[typing.Sequence[CaseStatus]] = None, tags: typing.Optional[typing.Sequence[str]] = None, - match_result: typing.Optional[typing.Sequence[MatchResult]] = None, - match_strength_v_1: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, + match_count: typing.Optional[MatchCount] = None, + match_strength: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, entity_types: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, risk_category: typing.Optional[typing.Sequence[RiskCategory]] = None, @@ -420,10 +420,10 @@ def get_project_entity( tags : typing.Optional[typing.Sequence[str]] Filter by tag IDs - match_result : typing.Optional[typing.Sequence[MatchResult]] - Filter by match result + match_count : typing.Optional[MatchCount] + Filter by match count - match_strength_v_1 : typing.Optional[typing.Sequence[MatchStrengthEnum]] + match_strength : typing.Optional[typing.Sequence[MatchStrengthEnum]] Filter by match strength entity_types : typing.Optional[typing.Sequence[str]] @@ -463,8 +463,8 @@ def get_project_entity( "uploads": uploads, "case_status": case_status, "tags": tags, - "match_result": match_result, - "match_strength_v1": match_strength_v_1, + "match_count": match_count, + "match_strength": match_strength, "entity_types": entity_types, "risk": risk, "risk_category": risk_category, @@ -1014,6 +1014,8 @@ def project_entity_supply_chain( project_id: str, project_entity_id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, @@ -1025,8 +1027,6 @@ def project_entity_supply_chain( tier_3_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_4_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_5_shipment_country: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -1046,6 +1046,12 @@ def project_entity_supply_chain( project_entity_id : str The project entity Identifier + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -1079,12 +1085,6 @@ def project_entity_supply_chain( tier_5_shipment_country : typing.Optional[typing.Sequence[Country]] Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -1119,17 +1119,18 @@ def project_entity_supply_chain( client_secret="YOUR_CLIENT_SECRET", ) client.project_entity.project_entity_supply_chain( - project_id="Gam5qG", - project_entity_id="GOeOE8", - min_date="2023-03-15", - product=["3204"], - risk=["forced_labor_xinjiang_origin_subtier"], + project_id="0n4473", + project_entity_id="yebNPJ", + product=["6004"], + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/upstream", method="GET", params={ + "product": product, + "-product": not_product, "risk": risk, "-risk": not_risk, "countries": countries, @@ -1141,8 +1142,6 @@ def project_entity_supply_chain( "tier3_shipment_country": tier_3_shipment_country, "tier4_shipment_country": tier_4_shipment_country, "tier5_shipment_country": tier_5_shipment_country, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, @@ -1231,12 +1230,12 @@ def project_entity_supply_chain_summary( project_id: str, project_entity_id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk_factors: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, not_countries: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -1256,6 +1255,12 @@ def project_entity_supply_chain_summary( project_entity_id : str The project entity Identifier + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk_factors : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -1268,12 +1273,6 @@ def project_entity_supply_chain_summary( not_countries : typing.Optional[typing.Sequence[Country]] Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -1308,29 +1307,21 @@ def project_entity_supply_chain_summary( client_secret="YOUR_CLIENT_SECRET", ) client.project_entity.project_entity_supply_chain_summary( - project_id="Gam5qG", - project_entity_id="GOeOE8", - min_date="2023-03-15", - product=["8536", "8544", "4016"], - risk_factors=[ - "forced_labor_xinjiang_name", - "forced_labor_xinjiang_uflpa", - "forced_labor_uflpa_origin_direct", - "exports_russian_gold", - "export_to_sanctioned", - ], + project_id="0n4473", + project_entity_id="yebNPJ", + max_depth=4, ) """ _response = self._client_wrapper.httpx_client.request( f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/upstream_summary", method="GET", params={ + "product": product, + "-product": not_product, "risk_factors": risk_factors, "-risk_factors": not_risk, "countries": countries, "-countries": not_countries, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, @@ -1561,8 +1552,8 @@ async def get_project_entities( uploads: typing.Optional[typing.Sequence[str]] = None, case_status: typing.Optional[typing.Sequence[CaseStatus]] = None, tags: typing.Optional[typing.Sequence[str]] = None, - match_result: typing.Optional[typing.Sequence[MatchResult]] = None, - match_strength_v_1: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, + match_count: typing.Optional[MatchCount] = None, + match_strength: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, entity_types: typing.Optional[typing.Sequence[str]] = None, geo_facets: typing.Optional[bool] = None, exact_match: typing.Optional[bool] = None, @@ -1598,10 +1589,10 @@ async def get_project_entities( tags : typing.Optional[typing.Sequence[str]] Filter by tag IDs - match_result : typing.Optional[typing.Sequence[MatchResult]] - Filter by match result + match_count : typing.Optional[MatchCount] + Filter by match count - match_strength_v_1 : typing.Optional[typing.Sequence[MatchStrengthEnum]] + match_strength : typing.Optional[typing.Sequence[MatchStrengthEnum]] Filter by match strength entity_types : typing.Optional[typing.Sequence[str]] @@ -1681,8 +1672,8 @@ async def main() -> None: "uploads": uploads, "case_status": case_status, "tags": tags, - "match_result": match_result, - "match_strength_v1": match_strength_v_1, + "match_count": match_count, + "match_strength": match_strength, "entity_types": entity_types, "geo_facets": geo_facets, "exact_match": exact_match, @@ -1783,8 +1774,8 @@ async def get_project_entity( uploads: typing.Optional[typing.Sequence[str]] = None, case_status: typing.Optional[typing.Sequence[CaseStatus]] = None, tags: typing.Optional[typing.Sequence[str]] = None, - match_result: typing.Optional[typing.Sequence[MatchResult]] = None, - match_strength_v_1: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, + match_count: typing.Optional[MatchCount] = None, + match_strength: typing.Optional[typing.Sequence[MatchStrengthEnum]] = None, entity_types: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, risk_category: typing.Optional[typing.Sequence[RiskCategory]] = None, @@ -1811,10 +1802,10 @@ async def get_project_entity( tags : typing.Optional[typing.Sequence[str]] Filter by tag IDs - match_result : typing.Optional[typing.Sequence[MatchResult]] - Filter by match result + match_count : typing.Optional[MatchCount] + Filter by match count - match_strength_v_1 : typing.Optional[typing.Sequence[MatchStrengthEnum]] + match_strength : typing.Optional[typing.Sequence[MatchStrengthEnum]] Filter by match strength entity_types : typing.Optional[typing.Sequence[str]] @@ -1862,8 +1853,8 @@ async def main() -> None: "uploads": uploads, "case_status": case_status, "tags": tags, - "match_result": match_result, - "match_strength_v1": match_strength_v_1, + "match_count": match_count, + "match_strength": match_strength, "entity_types": entity_types, "risk": risk, "risk_category": risk_category, @@ -2445,6 +2436,8 @@ async def project_entity_supply_chain( project_id: str, project_entity_id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, @@ -2456,8 +2449,6 @@ async def project_entity_supply_chain( tier_3_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_4_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_5_shipment_country: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -2477,6 +2468,12 @@ async def project_entity_supply_chain( project_entity_id : str The project entity Identifier + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -2510,12 +2507,6 @@ async def project_entity_supply_chain( tier_5_shipment_country : typing.Optional[typing.Sequence[Country]] Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -2555,11 +2546,10 @@ async def project_entity_supply_chain( async def main() -> None: await client.project_entity.project_entity_supply_chain( - project_id="Gam5qG", - project_entity_id="GOeOE8", - min_date="2023-03-15", - product=["3204"], - risk=["forced_labor_xinjiang_origin_subtier"], + project_id="0n4473", + project_entity_id="yebNPJ", + product=["6004"], + limit=1, ) @@ -2569,6 +2559,8 @@ async def main() -> None: f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/upstream", method="GET", params={ + "product": product, + "-product": not_product, "risk": risk, "-risk": not_risk, "countries": countries, @@ -2580,8 +2572,6 @@ async def main() -> None: "tier3_shipment_country": tier_3_shipment_country, "tier4_shipment_country": tier_4_shipment_country, "tier5_shipment_country": tier_5_shipment_country, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, @@ -2670,12 +2660,12 @@ async def project_entity_supply_chain_summary( project_id: str, project_entity_id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk_factors: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, not_countries: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -2695,6 +2685,12 @@ async def project_entity_supply_chain_summary( project_entity_id : str The project entity Identifier + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk_factors : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -2707,12 +2703,6 @@ async def project_entity_supply_chain_summary( not_countries : typing.Optional[typing.Sequence[Country]] Country leaf node filter. Only return supply chains that end with a supplier in none of the specified countries. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -2752,17 +2742,9 @@ async def project_entity_supply_chain_summary( async def main() -> None: await client.project_entity.project_entity_supply_chain_summary( - project_id="Gam5qG", - project_entity_id="GOeOE8", - min_date="2023-03-15", - product=["8536", "8544", "4016"], - risk_factors=[ - "forced_labor_xinjiang_name", - "forced_labor_xinjiang_uflpa", - "forced_labor_uflpa_origin_direct", - "exports_russian_gold", - "export_to_sanctioned", - ], + project_id="0n4473", + project_entity_id="yebNPJ", + max_depth=4, ) @@ -2772,12 +2754,12 @@ async def main() -> None: f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/upstream_summary", method="GET", params={ + "product": product, + "-product": not_product, "risk_factors": risk_factors, "-risk_factors": not_risk, "countries": countries, "-countries": not_countries, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, diff --git a/src/sayari/project_entity/types/__init__.py b/src/sayari/project_entity/types/__init__.py index 250941d5..02a1fae0 100644 --- a/src/sayari/project_entity/types/__init__.py +++ b/src/sayari/project_entity/types/__init__.py @@ -4,14 +4,18 @@ from .attribute_type import AttributeType from .attribute_types_response import AttributeTypesResponse from .attribute_values import AttributeValues +from .attributes_response import AttributesResponse from .business_purpose import BusinessPurpose from .case_status import CaseStatus from .count_type import CountType from .create_resolved_project_entity_request import CreateResolvedProjectEntityRequest from .facet_bucket import FacetBucket from .facets_response import FacetsResponse +from .grouped_attribute import GroupedAttribute +from .grouped_attribute_value import GroupedAttributeValue from .location import Location -from .match_result import MatchResult +from .match_count import MatchCount +from .match_profile_enum import MatchProfileEnum from .match_strength_enum import MatchStrengthEnum from .matched_attributes import MatchedAttributes from .product_bucket import ProductBucket @@ -25,6 +29,7 @@ from .project_entity_supply_chain_summary_response import ProjectEntitySupplyChainSummaryResponse from .project_entity_supply_chain_summary_response_data import ProjectEntitySupplyChainSummaryResponseData from .project_entity_supply_chain_upstream import ProjectEntitySupplyChainUpstream +from .project_risk_category import ProjectRiskCategory from .project_risk_factor import ProjectRiskFactor from .resolution_attributes import ResolutionAttributes from .resolution_profile import ResolutionProfile @@ -48,14 +53,18 @@ "AttributeType", "AttributeTypesResponse", "AttributeValues", + "AttributesResponse", "BusinessPurpose", "CaseStatus", "CountType", "CreateResolvedProjectEntityRequest", "FacetBucket", "FacetsResponse", + "GroupedAttribute", + "GroupedAttributeValue", "Location", - "MatchResult", + "MatchCount", + "MatchProfileEnum", "MatchStrengthEnum", "MatchedAttributes", "ProductBucket", @@ -69,6 +78,7 @@ "ProjectEntitySupplyChainSummaryResponse", "ProjectEntitySupplyChainSummaryResponseData", "ProjectEntitySupplyChainUpstream", + "ProjectRiskCategory", "ProjectRiskFactor", "ResolutionAttributes", "ResolutionProfile", diff --git a/src/sayari/project/types/hs_code_agg.py b/src/sayari/project_entity/types/attributes_response.py similarity index 78% rename from src/sayari/project/types/hs_code_agg.py rename to src/sayari/project_entity/types/attributes_response.py index 6bd27b37..7a96e2d2 100644 --- a/src/sayari/project/types/hs_code_agg.py +++ b/src/sayari/project_entity/types/attributes_response.py @@ -1,15 +1,14 @@ # This file was auto-generated by Fern from our API Definition. from ...core.pydantic_utilities import UniversalBaseModel -from .hs_code_agg_terms import HsCodeAggTerms -from ...core.pydantic_utilities import IS_PYDANTIC_V2 import typing +from .grouped_attribute import GroupedAttribute +from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic -class HsCodeAgg(UniversalBaseModel): - doc_count: int - hs_code_terms: HsCodeAggTerms +class AttributesResponse(UniversalBaseModel): + data: typing.List[GroupedAttribute] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project/types/hs_code_agg_terms.py b/src/sayari/project_entity/types/grouped_attribute.py similarity index 71% rename from src/sayari/project/types/hs_code_agg_terms.py rename to src/sayari/project_entity/types/grouped_attribute.py index 17694ead..1c8a5842 100644 --- a/src/sayari/project/types/hs_code_agg_terms.py +++ b/src/sayari/project_entity/types/grouped_attribute.py @@ -2,15 +2,15 @@ from ...core.pydantic_utilities import UniversalBaseModel import typing -from .hs_code_agg_bucket import HsCodeAggBucket +from .grouped_attribute_value import GroupedAttributeValue from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic -class HsCodeAggTerms(UniversalBaseModel): - doc_count_error_upper_bound: int - sum_other_doc_count: int - buckets: typing.List[HsCodeAggBucket] +class GroupedAttribute(UniversalBaseModel): + field: str + match_resolution: bool + values: typing.List[GroupedAttributeValue] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project/types/hs_code_agg_bucket.py b/src/sayari/project_entity/types/grouped_attribute_value.py similarity index 74% rename from src/sayari/project/types/hs_code_agg_bucket.py rename to src/sayari/project_entity/types/grouped_attribute_value.py index e4df0e38..159d6b89 100644 --- a/src/sayari/project/types/hs_code_agg_bucket.py +++ b/src/sayari/project_entity/types/grouped_attribute_value.py @@ -1,16 +1,14 @@ # This file was auto-generated by Fern from our API Definition. from ...core.pydantic_utilities import UniversalBaseModel -import typing -from .int_key_value import IntKeyValue from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing import pydantic -class HsCodeAggBucket(UniversalBaseModel): - key: str - doc_count: int - hs_code_sums: typing.Optional[IntKeyValue] = None +class GroupedAttributeValue(UniversalBaseModel): + id: str + value: str if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project_entity/types/match_count.py b/src/sayari/project_entity/types/match_count.py new file mode 100644 index 00000000..e87a8660 --- /dev/null +++ b/src/sayari/project_entity/types/match_count.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +MatchCount = typing.Union[typing.Literal["one", "many"], typing.Any] diff --git a/src/sayari/project_entity/types/match_profile_enum.py b/src/sayari/project_entity/types/match_profile_enum.py new file mode 100644 index 00000000..6a86c378 --- /dev/null +++ b/src/sayari/project_entity/types/match_profile_enum.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +MatchProfileEnum = typing.Union[typing.Literal["corporate", "suppliers", "screen", "search"], typing.Any] diff --git a/src/sayari/project_entity/types/match_result.py b/src/sayari/project_entity/types/match_result.py deleted file mode 100644 index 2a9e1e8f..00000000 --- a/src/sayari/project_entity/types/match_result.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -MatchResult = typing.Union[typing.Literal["ambiguous", "unambiguous", "unresolved", "sayari"], typing.Any] diff --git a/src/sayari/project_entity/types/project_entities_response.py b/src/sayari/project_entity/types/project_entities_response.py index 83e03c86..abbcc145 100644 --- a/src/sayari/project_entity/types/project_entities_response.py +++ b/src/sayari/project_entity/types/project_entities_response.py @@ -21,6 +21,7 @@ class ProjectEntitiesResponse(UniversalBaseModel): ProjectEntitiesResponse, ProjectEntityMatchResponse, ProjectEntityResponse, + ProjectRiskCategory, ProjectRiskFactor, SourceField, TradeCounts, @@ -55,6 +56,89 @@ class ProjectEntitiesResponse(UniversalBaseModel): values=["253400V1H6ART1UQ0N98"], ), }, + countries=[ + "USA", + "CYP", + "ITA", + "CHN", + "RUS", + "UKR", + "IND", + "IRL", + "KAZ", + "DEU", + ], + risk_categories=[ + ProjectRiskCategory( + id="regulatory_action", + label="Regulatory action", + risk_factors=["regulatory_action"], + ), + ProjectRiskCategory( + id="export_controls", + label="Export controls", + risk_factors=["meu_list_contractors", "export_controls"], + ), + ProjectRiskCategory( + id="political_exposure", + label="Political exposure", + risk_factors=["soe_adjacent", "pep_adjacent"], + ), + ProjectRiskCategory( + id="sanctions", + label="Sanctions", + risk_factors=["sanctioned", "formerly_sanctioned"], + ), + ProjectRiskCategory( + id="adverse_media", + label="Adverse media", + risk_factors=["reputational_risk_other"], + ), + ], + risk_factors=[ + ProjectRiskFactor( + id="regulatory_action", + ), + ProjectRiskFactor( + id="sanctioned", + ), + ProjectRiskFactor( + id="meu_list_contractors", + ), + ProjectRiskFactor( + id="reputational_risk_other", + ), + ProjectRiskFactor( + id="pep_adjacent", + ), + ProjectRiskFactor( + id="state_owned", + ), + ProjectRiskFactor( + id="export_controls", + ), + ProjectRiskFactor( + id="formerly_sanctioned", + ), + ProjectRiskFactor( + id="basel_aml", + ), + ProjectRiskFactor( + id="cpi_score", + ), + ], + upstream=UpstreamInfo( + risk_factors=[], + countries=[], + trade_counts=TradeCounts( + shipper_of=56, + receiver_of=2, + ), + has_upstream=False, + products=[], + ), + tags=[], + case="not_assigned", matches=[ ProjectEntityMatchResponse( match_id="52z4Wa:dy-rh2g0QtzUN_jC_e9S_A", @@ -94,6 +178,36 @@ class ProjectEntitiesResponse(UniversalBaseModel): "KAZ", "DEU", ], + risk_categories=[ + ProjectRiskCategory( + id="regulatory_action", + label="Regulatory action", + risk_factors=["regulatory_action"], + ), + ProjectRiskCategory( + id="export_controls", + label="Export controls", + risk_factors=[ + "meu_list_contractors", + "export_controls", + ], + ), + ProjectRiskCategory( + id="political_exposure", + label="Political exposure", + risk_factors=["soe_adjacent", "pep_adjacent"], + ), + ProjectRiskCategory( + id="sanctions", + label="Sanctions", + risk_factors=["sanctioned", "formerly_sanctioned"], + ), + ProjectRiskCategory( + id="adverse_media", + label="Adverse media", + risk_factors=["reputational_risk_other"], + ), + ], risk_factors=[ ProjectRiskFactor( id="regulatory_action", @@ -366,8 +480,6 @@ class ProjectEntitiesResponse(UniversalBaseModel): updated_at="2025-04-22 22:54:00.913586+00", ) ], - tags=[], - case="not_assigned", ) ], size=QualifiedCount( diff --git a/src/sayari/project_entity/types/project_entity_match_response.py b/src/sayari/project_entity/types/project_entity_match_response.py index a3cbbbac..2fab5108 100644 --- a/src/sayari/project_entity/types/project_entity_match_response.py +++ b/src/sayari/project_entity/types/project_entity_match_response.py @@ -3,11 +3,13 @@ from ...core.pydantic_utilities import UniversalBaseModel from .matched_attributes import MatchedAttributes import typing +from .project_risk_category import ProjectRiskCategory from .project_risk_factor import ProjectRiskFactor from .business_purpose import BusinessPurpose from .upstream_info import UpstreamInfo from .source_field import SourceField from .address import Address +from .match_profile_enum import MatchProfileEnum from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -19,6 +21,7 @@ class ProjectEntityMatchResponse(UniversalBaseModel): label: str matched_attributes: MatchedAttributes countries: typing.List[str] + risk_categories: typing.List[ProjectRiskCategory] risk_factors: typing.List[ProjectRiskFactor] business_purpose: typing.List[BusinessPurpose] upstream: UpstreamInfo @@ -27,7 +30,7 @@ class ProjectEntityMatchResponse(UniversalBaseModel): hs_codes: typing.List[str] created_at: str updated_at: typing.Optional[str] = None - resolution_profile: typing.Optional[str] = None + match_profile: typing.Optional[MatchProfileEnum] = None deleted_at: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/sayari/project_entity/types/project_entity_response.py b/src/sayari/project_entity/types/project_entity_response.py index 4e205781..11b7dcc5 100644 --- a/src/sayari/project_entity/types/project_entity_response.py +++ b/src/sayari/project_entity/types/project_entity_response.py @@ -4,10 +4,12 @@ import typing from .match_strength_enum import MatchStrengthEnum from .attribute_values import AttributeValues -from .product_mapping import ProductMapping -from .project_entity_match_response import ProjectEntityMatchResponse +from .project_risk_category import ProjectRiskCategory +from .project_risk_factor import ProjectRiskFactor +from .upstream_info import UpstreamInfo from .tag_response import TagResponse from .case_status import CaseStatus +from .project_entity_match_response import ProjectEntityMatchResponse from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -20,10 +22,13 @@ class ProjectEntityResponse(UniversalBaseModel): strength: MatchStrengthEnum created_at: str attributes: typing.Dict[str, AttributeValues] - product_mapping: typing.Optional[ProductMapping] = None - matches: typing.List[ProjectEntityMatchResponse] + countries: typing.List[str] + risk_categories: typing.List[ProjectRiskCategory] + risk_factors: typing.List[ProjectRiskFactor] + upstream: UpstreamInfo tags: typing.List[TagResponse] case: typing.Optional[CaseStatus] = None + matches: typing.List[ProjectEntityMatchResponse] updated_at: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/sayari/project_entity/types/project_risk_category.py b/src/sayari/project_entity/types/project_risk_category.py new file mode 100644 index 00000000..eb159c52 --- /dev/null +++ b/src/sayari/project_entity/types/project_risk_category.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProjectRiskCategory(UniversalBaseModel): + id: str + label: str + risk_factors: typing.List[str] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity/types/single_project_entity_response.py b/src/sayari/project_entity/types/single_project_entity_response.py index 6724c644..f8319bb0 100644 --- a/src/sayari/project_entity/types/single_project_entity_response.py +++ b/src/sayari/project_entity/types/single_project_entity_response.py @@ -16,9 +16,9 @@ class SingleProjectEntityResponse(UniversalBaseModel): AttributeValues, BusinessPurpose, MatchedAttributes, - ProductMapping, ProjectEntityMatchResponse, ProjectEntityResponse, + ProjectRiskCategory, ProjectRiskFactor, SingleProjectEntityResponse, SourceField, @@ -52,10 +52,89 @@ class SingleProjectEntityResponse(UniversalBaseModel): values=["253400V1H6ART1UQ0N98"], ), }, - product_mapping=ProductMapping( - state="unmapped", + countries=[ + "USA", + "CYP", + "ITA", + "CHN", + "RUS", + "UKR", + "IND", + "IRL", + "KAZ", + "DEU", + ], + risk_categories=[ + ProjectRiskCategory( + id="regulatory_action", + label="Regulatory action", + risk_factors=["regulatory_action"], + ), + ProjectRiskCategory( + id="export_controls", + label="Export controls", + risk_factors=["meu_list_contractors", "export_controls"], + ), + ProjectRiskCategory( + id="political_exposure", + label="Political exposure", + risk_factors=["soe_adjacent", "pep_adjacent"], + ), + ProjectRiskCategory( + id="sanctions", + label="Sanctions", + risk_factors=["sanctioned", "formerly_sanctioned"], + ), + ProjectRiskCategory( + id="adverse_media", + label="Adverse media", + risk_factors=["reputational_risk_other"], + ), + ], + risk_factors=[ + ProjectRiskFactor( + id="regulatory_action", + ), + ProjectRiskFactor( + id="sanctioned", + ), + ProjectRiskFactor( + id="meu_list_contractors", + ), + ProjectRiskFactor( + id="reputational_risk_other", + ), + ProjectRiskFactor( + id="pep_adjacent", + ), + ProjectRiskFactor( + id="state_owned", + ), + ProjectRiskFactor( + id="export_controls", + ), + ProjectRiskFactor( + id="formerly_sanctioned", + ), + ProjectRiskFactor( + id="basel_aml", + ), + ProjectRiskFactor( + id="cpi_score", + ), + ], + upstream=UpstreamInfo( + risk_factors=[], + countries=[], + trade_counts=TradeCounts( + shipper_of=56, + receiver_of=2, + ), + has_upstream=False, products=[], ), + tags=[], + case="not_assigned", matches=[ ProjectEntityMatchResponse( match_id="52z4Wa:dy-rh2g0QtzUN_jC_e9S_A", @@ -95,6 +174,36 @@ class SingleProjectEntityResponse(UniversalBaseModel): "KAZ", "DEU", ], + risk_categories=[ + ProjectRiskCategory( + id="regulatory_action", + label="Regulatory action", + risk_factors=["regulatory_action"], + ), + ProjectRiskCategory( + id="export_controls", + label="Export controls", + risk_factors=[ + "meu_list_contractors", + "export_controls", + ], + ), + ProjectRiskCategory( + id="political_exposure", + label="Political exposure", + risk_factors=["soe_adjacent", "pep_adjacent"], + ), + ProjectRiskCategory( + id="sanctions", + label="Sanctions", + risk_factors=["sanctioned", "formerly_sanctioned"], + ), + ProjectRiskCategory( + id="adverse_media", + label="Adverse media", + risk_factors=["reputational_risk_other"], + ), + ], risk_factors=[ ProjectRiskFactor( id="regulatory_action", @@ -369,8 +478,6 @@ class SingleProjectEntityResponse(UniversalBaseModel): updated_at="2025-04-22 22:54:00.913586+00", ) ], - tags=[], - case="not_assigned", ), ) """ diff --git a/src/sayari/project_entity_attributes/__init__.py b/src/sayari/project_entity_attributes/__init__.py new file mode 100644 index 00000000..7ba8a944 --- /dev/null +++ b/src/sayari/project_entity_attributes/__init__.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + UpdateProjectEntityAttributeRequest, + UpdateProjectEntityAttributeResponse, + UpdateProjectEntityAttributeResponseData, +) + +__all__ = [ + "UpdateProjectEntityAttributeRequest", + "UpdateProjectEntityAttributeResponse", + "UpdateProjectEntityAttributeResponseData", +] diff --git a/src/sayari/project_entity_attributes/client.py b/src/sayari/project_entity_attributes/client.py new file mode 100644 index 00000000..7bb2d741 --- /dev/null +++ b/src/sayari/project_entity_attributes/client.py @@ -0,0 +1,310 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from .types.update_project_entity_attribute_request import UpdateProjectEntityAttributeRequest +from ..core.request_options import RequestOptions +from .types.update_project_entity_attribute_response import UpdateProjectEntityAttributeResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.pydantic_utilities import parse_obj_as +from ..shared_errors.errors.bad_request import BadRequest +from ..shared_errors.types.bad_request_response import BadRequestResponse +from ..shared_errors.errors.unauthorized import Unauthorized +from ..shared_errors.types.unauthorized_response import UnauthorizedResponse +from ..shared_errors.errors.not_found import NotFound +from ..shared_errors.types.not_found_response import NotFoundResponse +from ..shared_errors.errors.method_not_allowed import MethodNotAllowed +from ..shared_errors.types.method_not_allowed_response import MethodNotAllowedResponse +from ..shared_errors.errors.rate_limit_exceeded import RateLimitExceeded +from ..shared_errors.types.rate_limit_response import RateLimitResponse +from ..shared_errors.errors.internal_server_error import InternalServerError +from ..shared_errors.types.internal_server_error_response import InternalServerErrorResponse +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ProjectEntityAttributesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def update_project_entity_attribute( + self, + project_id: str, + project_entity_id: str, + attribute_id: str, + *, + request: UpdateProjectEntityAttributeRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityAttributeResponse: + """ + Updates a specific attribute for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + attribute_id : str + + request : UpdateProjectEntityAttributeRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityAttributeResponse + + Examples + -------- + from sayari import Sayari + from sayari.project_entity_attributes import UpdateProjectEntityAttributeRequest + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity_attributes.update_project_entity_attribute( + project_id="V03eYM", + project_entity_id="BG72YW", + attribute_id="xG8wYP", + request=UpdateProjectEntityAttributeRequest( + field="name", + value="updated name", + match_resolution=True, + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/attributes/{jsonable_encoder(attribute_id)}", + method="PUT", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityAttributeRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityAttributeResponse, + parse_obj_as( + type_=UpdateProjectEntityAttributeResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncProjectEntityAttributesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def update_project_entity_attribute( + self, + project_id: str, + project_entity_id: str, + attribute_id: str, + *, + request: UpdateProjectEntityAttributeRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityAttributeResponse: + """ + Updates a specific attribute for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + attribute_id : str + + request : UpdateProjectEntityAttributeRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityAttributeResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + from sayari.project_entity_attributes import UpdateProjectEntityAttributeRequest + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity_attributes.update_project_entity_attribute( + project_id="V03eYM", + project_entity_id="BG72YW", + attribute_id="xG8wYP", + request=UpdateProjectEntityAttributeRequest( + field="name", + value="updated name", + match_resolution=True, + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/attributes/{jsonable_encoder(attribute_id)}", + method="PUT", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityAttributeRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityAttributeResponse, + parse_obj_as( + type_=UpdateProjectEntityAttributeResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/sayari/project_entity_attributes/types/__init__.py b/src/sayari/project_entity_attributes/types/__init__.py new file mode 100644 index 00000000..d9b20917 --- /dev/null +++ b/src/sayari/project_entity_attributes/types/__init__.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +from .update_project_entity_attribute_request import UpdateProjectEntityAttributeRequest +from .update_project_entity_attribute_response import UpdateProjectEntityAttributeResponse +from .update_project_entity_attribute_response_data import UpdateProjectEntityAttributeResponseData + +__all__ = [ + "UpdateProjectEntityAttributeRequest", + "UpdateProjectEntityAttributeResponse", + "UpdateProjectEntityAttributeResponseData", +] diff --git a/src/sayari/project_entity_attributes/types/update_project_entity_attribute_request.py b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_request.py new file mode 100644 index 00000000..845fc91f --- /dev/null +++ b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_request.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class UpdateProjectEntityAttributeRequest(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_attributes import UpdateProjectEntityAttributeRequest + + UpdateProjectEntityAttributeRequest( + field="name", + value="updated name", + match_resolution=True, + ) + """ + + field: str + value: str + match_resolution: bool + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response.py b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response.py new file mode 100644 index 00000000..62c230a3 --- /dev/null +++ b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from .update_project_entity_attribute_response_data import UpdateProjectEntityAttributeResponseData +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class UpdateProjectEntityAttributeResponse(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_attributes import ( + UpdateProjectEntityAttributeResponse, + UpdateProjectEntityAttributeResponseData, + ) + + UpdateProjectEntityAttributeResponse( + data=UpdateProjectEntityAttributeResponseData( + id="xG8wYP", + field="name", + value="updated name", + match_resolution=True, + ), + ) + """ + + data: UpdateProjectEntityAttributeResponseData + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response_data.py b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response_data.py new file mode 100644 index 00000000..f1acceed --- /dev/null +++ b/src/sayari/project_entity_attributes/types/update_project_entity_attribute_response_data.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class UpdateProjectEntityAttributeResponseData(UniversalBaseModel): + id: str + field: str + value: str + match_resolution: bool + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/__init__.py b/src/sayari/project_entity_supply_chain_snapshots/__init__.py new file mode 100644 index 00000000..b86fce6e --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/__init__.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + CreateProjectEntitySupplyChainSnapshotRequest, + CreateProjectEntitySupplyChainSnapshotResponse, + ProjectEntitySupplyChainSnapshotByIdResponse, + ProjectEntitySupplyChainSnapshotData, + ProjectEntitySupplyChainSnapshotDetailData, + ProjectEntitySupplyChainSnapshotsResponse, + SupplyChainEdge, + SupplyChainNode, +) + +__all__ = [ + "CreateProjectEntitySupplyChainSnapshotRequest", + "CreateProjectEntitySupplyChainSnapshotResponse", + "ProjectEntitySupplyChainSnapshotByIdResponse", + "ProjectEntitySupplyChainSnapshotData", + "ProjectEntitySupplyChainSnapshotDetailData", + "ProjectEntitySupplyChainSnapshotsResponse", + "SupplyChainEdge", + "SupplyChainNode", +] diff --git a/src/sayari/project_entity_supply_chain_snapshots/client.py b/src/sayari/project_entity_supply_chain_snapshots/client.py new file mode 100644 index 00000000..3b2c7258 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/client.py @@ -0,0 +1,1014 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from ..core.request_options import RequestOptions +from .types.project_entity_supply_chain_snapshots_response import ProjectEntitySupplyChainSnapshotsResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..shared_errors.errors.bad_request import BadRequest +from ..shared_errors.types.bad_request_response import BadRequestResponse +from ..shared_errors.errors.unauthorized import Unauthorized +from ..shared_errors.types.unauthorized_response import UnauthorizedResponse +from ..shared_errors.errors.not_found import NotFound +from ..shared_errors.types.not_found_response import NotFoundResponse +from ..shared_errors.errors.method_not_allowed import MethodNotAllowed +from ..shared_errors.types.method_not_allowed_response import MethodNotAllowedResponse +from ..shared_errors.errors.rate_limit_exceeded import RateLimitExceeded +from ..shared_errors.types.rate_limit_response import RateLimitResponse +from ..shared_errors.errors.internal_server_error import InternalServerError +from ..shared_errors.types.internal_server_error_response import InternalServerErrorResponse +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from .types.project_entity_supply_chain_snapshot_by_id_response import ProjectEntitySupplyChainSnapshotByIdResponse +from .types.create_project_entity_supply_chain_snapshot_request import CreateProjectEntitySupplyChainSnapshotRequest +from .types.create_project_entity_supply_chain_snapshot_response import CreateProjectEntitySupplyChainSnapshotResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ProjectEntitySupplyChainSnapshotsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_project_entity_supply_chain_snapshots( + self, project_id: str, project_entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> ProjectEntitySupplyChainSnapshotsResponse: + """ + Retrieves all supply chain snapshots for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectEntitySupplyChainSnapshotsResponse + + Examples + -------- + from sayari import Sayari + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshots( + project_id="V03eYM", + project_entity_id="BG72YW", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectEntitySupplyChainSnapshotsResponse, + parse_obj_as( + type_=ProjectEntitySupplyChainSnapshotsResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_project_entity_supply_chain_snapshot_by_id( + self, + project_id: str, + project_entity_id: str, + snapshot_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> ProjectEntitySupplyChainSnapshotByIdResponse: + """ + Retrieves a specific supply chain snapshot by ID for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + snapshot_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectEntitySupplyChainSnapshotByIdResponse + + Examples + -------- + from sayari import Sayari + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshot_by_id( + project_id="V03eYM", + project_entity_id="BG72YW", + snapshot_id="sN4p2K", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots/{jsonable_encoder(snapshot_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectEntitySupplyChainSnapshotByIdResponse, + parse_obj_as( + type_=ProjectEntitySupplyChainSnapshotByIdResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_project_entity_supply_chain_snapshot( + self, + project_id: str, + project_entity_id: str, + *, + request: CreateProjectEntitySupplyChainSnapshotRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> CreateProjectEntitySupplyChainSnapshotResponse: + """ + Creates a new supply chain snapshot for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : CreateProjectEntitySupplyChainSnapshotRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateProjectEntitySupplyChainSnapshotResponse + + Examples + -------- + from sayari import Sayari + from sayari.project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotRequest, + ) + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity_supply_chain_snapshots.create_project_entity_supply_chain_snapshot( + project_id="V03eYM", + project_entity_id="BG72YW", + request=CreateProjectEntitySupplyChainSnapshotRequest( + label="Q1 2024 Supply Chain Analysis", + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=CreateProjectEntitySupplyChainSnapshotRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CreateProjectEntitySupplyChainSnapshotResponse, + parse_obj_as( + type_=CreateProjectEntitySupplyChainSnapshotResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_project_entity_supply_chain_snapshot_by_id( + self, + project_id: str, + project_entity_id: str, + snapshot_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Deletes a specific supply chain snapshot by ID for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + snapshot_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from sayari import Sayari + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity_supply_chain_snapshots.delete_project_entity_supply_chain_snapshot_by_id( + project_id="project_id", + project_entity_id="project_entity_id", + snapshot_id="snapshot_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots/{jsonable_encoder(snapshot_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncProjectEntitySupplyChainSnapshotsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_project_entity_supply_chain_snapshots( + self, project_id: str, project_entity_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> ProjectEntitySupplyChainSnapshotsResponse: + """ + Retrieves all supply chain snapshots for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectEntitySupplyChainSnapshotsResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshots( + project_id="V03eYM", + project_entity_id="BG72YW", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectEntitySupplyChainSnapshotsResponse, + parse_obj_as( + type_=ProjectEntitySupplyChainSnapshotsResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_project_entity_supply_chain_snapshot_by_id( + self, + project_id: str, + project_entity_id: str, + snapshot_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> ProjectEntitySupplyChainSnapshotByIdResponse: + """ + Retrieves a specific supply chain snapshot by ID for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + snapshot_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectEntitySupplyChainSnapshotByIdResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity_supply_chain_snapshots.get_project_entity_supply_chain_snapshot_by_id( + project_id="V03eYM", + project_entity_id="BG72YW", + snapshot_id="sN4p2K", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots/{jsonable_encoder(snapshot_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ProjectEntitySupplyChainSnapshotByIdResponse, + parse_obj_as( + type_=ProjectEntitySupplyChainSnapshotByIdResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_project_entity_supply_chain_snapshot( + self, + project_id: str, + project_entity_id: str, + *, + request: CreateProjectEntitySupplyChainSnapshotRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> CreateProjectEntitySupplyChainSnapshotResponse: + """ + Creates a new supply chain snapshot for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : CreateProjectEntitySupplyChainSnapshotRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateProjectEntitySupplyChainSnapshotResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + from sayari.project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotRequest, + ) + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity_supply_chain_snapshots.create_project_entity_supply_chain_snapshot( + project_id="V03eYM", + project_entity_id="BG72YW", + request=CreateProjectEntitySupplyChainSnapshotRequest( + label="Q1 2024 Supply Chain Analysis", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=CreateProjectEntitySupplyChainSnapshotRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CreateProjectEntitySupplyChainSnapshotResponse, + parse_obj_as( + type_=CreateProjectEntitySupplyChainSnapshotResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_project_entity_supply_chain_snapshot_by_id( + self, + project_id: str, + project_entity_id: str, + snapshot_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Deletes a specific supply chain snapshot by ID for a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + snapshot_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity_supply_chain_snapshots.delete_project_entity_supply_chain_snapshot_by_id( + project_id="project_id", + project_entity_id="project_entity_id", + snapshot_id="snapshot_id", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/supply_chain/snapshots/{jsonable_encoder(snapshot_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/__init__.py b/src/sayari/project_entity_supply_chain_snapshots/types/__init__.py new file mode 100644 index 00000000..bda52c12 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +from .create_project_entity_supply_chain_snapshot_request import CreateProjectEntitySupplyChainSnapshotRequest +from .create_project_entity_supply_chain_snapshot_response import CreateProjectEntitySupplyChainSnapshotResponse +from .project_entity_supply_chain_snapshot_by_id_response import ProjectEntitySupplyChainSnapshotByIdResponse +from .project_entity_supply_chain_snapshot_data import ProjectEntitySupplyChainSnapshotData +from .project_entity_supply_chain_snapshot_detail_data import ProjectEntitySupplyChainSnapshotDetailData +from .project_entity_supply_chain_snapshots_response import ProjectEntitySupplyChainSnapshotsResponse +from .supply_chain_edge import SupplyChainEdge +from .supply_chain_node import SupplyChainNode + +__all__ = [ + "CreateProjectEntitySupplyChainSnapshotRequest", + "CreateProjectEntitySupplyChainSnapshotResponse", + "ProjectEntitySupplyChainSnapshotByIdResponse", + "ProjectEntitySupplyChainSnapshotData", + "ProjectEntitySupplyChainSnapshotDetailData", + "ProjectEntitySupplyChainSnapshotsResponse", + "SupplyChainEdge", + "SupplyChainNode", +] diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_request.py b/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_request.py new file mode 100644 index 00000000..e5af5b03 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_request.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class CreateProjectEntitySupplyChainSnapshotRequest(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotRequest, + ) + + CreateProjectEntitySupplyChainSnapshotRequest( + label="Q1 2024 Supply Chain Analysis", + ) + """ + + label: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_response.py b/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_response.py new file mode 100644 index 00000000..f5fb9a10 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/create_project_entity_supply_chain_snapshot_response.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class CreateProjectEntitySupplyChainSnapshotResponse(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_supply_chain_snapshots import ( + CreateProjectEntitySupplyChainSnapshotResponse, + ) + + CreateProjectEntitySupplyChainSnapshotResponse( + snapshot_id="nK9mP2", + ) + """ + + snapshot_id: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_by_id_response.py b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_by_id_response.py new file mode 100644 index 00000000..15edb5de --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_by_id_response.py @@ -0,0 +1,109 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from .project_entity_supply_chain_snapshot_detail_data import ProjectEntitySupplyChainSnapshotDetailData +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class ProjectEntitySupplyChainSnapshotByIdResponse(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_supply_chain_snapshots import ( + ProjectEntitySupplyChainSnapshotByIdResponse, + ProjectEntitySupplyChainSnapshotDetailData, + SupplyChainEdge, + SupplyChainNode, + ) + + ProjectEntitySupplyChainSnapshotByIdResponse( + data=ProjectEntitySupplyChainSnapshotDetailData( + snapshot_id="nK9mP2", + label="Production Supply Chain Analysis", + release_tag="20250115143000_prod", + partial_results=True, + explored_count=15, + created_at="2025-01-15 14:30:00.12345+00", + updated_at="2025-01-15 14:30:00.12345+00", + nodes=[ + SupplyChainNode( + id="xG8wYP", + entity_id="oSlRbVMw4JdQ_R0nTd7yaQ", + label="TechCorp Inc", + type="company", + risk_factors=[ + "export_controls", + "former_wro_entity", + "export_to_soe", + ], + countries=["USA", "CHN"], + ), + SupplyChainNode( + id="6GaxYn", + entity_id="rSoUePz7MgU_U3qWg0bdT", + label="Trade Partners Ltd", + type="company", + risk_factors=[ + "export_controls", + "former_wro_entity", + "export_to_soe", + ], + countries=["RUS", "IRN"], + ), + SupplyChainNode( + id="JGlwYl", + entity_id="sTpVfQa8NhV_V4rXh1ceU", + label="International Logistics", + type="company", + risk_factors=["export_to_soe"], + countries=["GBR", "NLD"], + ), + ], + edges=[ + SupplyChainEdge( + id="xG8wYP", + src_id="6GaxYn", + dst_id="xG8wYP", + departure_countries=["AFG"], + arrival_countries=["AFG", "AGO"], + hs_code="0303", + min_date="51969-08-29T00:00:00+00:00", + max_date="52971-09-25T00:00:00+00:00", + ), + SupplyChainEdge( + id="6GaxYn", + src_id="6GaxYn", + dst_id="JGlwYl", + departure_countries=["AFG"], + arrival_countries=["AFG", "AGO"], + hs_code="0304", + min_date="51969-08-29T00:00:00+00:00", + max_date="52971-09-25T00:00:00+00:00", + ), + SupplyChainEdge( + id="V03eYM", + src_id="xG8wYP", + dst_id="JGlwYl", + departure_countries=["USA", "CHN"], + arrival_countries=["GBR", "NLD"], + hs_code="0303", + min_date="51969-08-29T00:00:00+00:00", + max_date="52971-09-25T00:00:00+00:00", + ), + ], + ), + ) + """ + + data: ProjectEntitySupplyChainSnapshotDetailData + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_data.py b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_data.py new file mode 100644 index 00000000..93cadf01 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_data.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class ProjectEntitySupplyChainSnapshotData(UniversalBaseModel): + snapshot_id: str + label: str + release_tag: str + partial_results: bool + explored_count: int + created_at: str + updated_at: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_detail_data.py b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_detail_data.py new file mode 100644 index 00000000..0fd57ee5 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshot_detail_data.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +from .supply_chain_node import SupplyChainNode +from .supply_chain_edge import SupplyChainEdge +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProjectEntitySupplyChainSnapshotDetailData(UniversalBaseModel): + snapshot_id: str + label: str + release_tag: str + partial_results: bool + explored_count: int + created_at: str + updated_at: str + nodes: typing.List[SupplyChainNode] + edges: typing.List[SupplyChainEdge] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshots_response.py b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshots_response.py new file mode 100644 index 00000000..3a41347c --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/project_entity_supply_chain_snapshots_response.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +from .project_entity_supply_chain_snapshot_data import ProjectEntitySupplyChainSnapshotData +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProjectEntitySupplyChainSnapshotsResponse(UniversalBaseModel): + """ + Examples + -------- + from sayari.project_entity_supply_chain_snapshots import ( + ProjectEntitySupplyChainSnapshotData, + ProjectEntitySupplyChainSnapshotsResponse, + ) + + ProjectEntitySupplyChainSnapshotsResponse( + data=[ + ProjectEntitySupplyChainSnapshotData( + snapshot_id="xG8wYP", + label="My REST Snapshot", + release_tag="20220429212557_test", + partial_results=False, + explored_count=6, + created_at="2025-08-12 20:13:20.49643+00", + updated_at="2025-08-12 20:13:20.49643+00", + ) + ], + ) + """ + + data: typing.List[ProjectEntitySupplyChainSnapshotData] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_edge.py b/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_edge.py new file mode 100644 index 00000000..14e9afd2 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_edge.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SupplyChainEdge(UniversalBaseModel): + id: str + src_id: str + dst_id: str + departure_countries: typing.List[str] + arrival_countries: typing.List[str] + hs_code: str + min_date: str + max_date: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_node.py b/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_node.py new file mode 100644 index 00000000..8280a316 --- /dev/null +++ b/src/sayari/project_entity_supply_chain_snapshots/types/supply_chain_node.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SupplyChainNode(UniversalBaseModel): + id: str + entity_id: str + label: str + type: str + risk_factors: typing.List[str] + countries: typing.List[str] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/sayari/search/types/entity_search_response.py b/src/sayari/search/types/entity_search_response.py index 93f5c5bd..b646a4be 100644 --- a/src/sayari/search/types/entity_search_response.py +++ b/src/sayari/search/types/entity_search_response.py @@ -155,6 +155,7 @@ class EntitySearchResponse(PaginatedResponse): "address": 6, }, reference_id="ecdfb3f2ecc8c3797e77d5795a8066ef/06517802/1540252800000:4a34442eccf1622995130b194a5d50e7", + logistics_entity=False, coordinates=[ Coordinates( lat=51.49322001798694, diff --git a/src/sayari/search/types/filter_list.py b/src/sayari/search/types/filter_list.py index 7df412d8..99a0b6e2 100644 --- a/src/sayari/search/types/filter_list.py +++ b/src/sayari/search/types/filter_list.py @@ -21,6 +21,11 @@ class FilterList(UniversalBaseModel): List of source IDs to filter by. """ + source_country: typing.Optional[typing.List[Country]] = pydantic.Field(default=None) + """ + List of source countries to filter by. Must be specified as trigrams, e.g. ATF. + """ + country: typing.Optional[typing.List[Country]] = pydantic.Field(default=None) """ List of countries to filter by. diff --git a/src/sayari/shared_types/types/core_entity.py b/src/sayari/shared_types/types/core_entity.py index 276667c6..17b30c92 100644 --- a/src/sayari/shared_types/types/core_entity.py +++ b/src/sayari/shared_types/types/core_entity.py @@ -103,6 +103,7 @@ class CoreEntity(EntitySummary): edited_by: typing.Optional[str] = None editable: typing.Optional[bool] = None upload: typing.Optional[str] = None + logistics_entity: typing.Optional[bool] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/shared_types/types/embedded_entity.py b/src/sayari/shared_types/types/embedded_entity.py index c34c8e95..0200ca1c 100644 --- a/src/sayari/shared_types/types/embedded_entity.py +++ b/src/sayari/shared_types/types/embedded_entity.py @@ -111,6 +111,7 @@ class EmbeddedEntity(UniversalBaseModel): user_related_entities_count: int user_record_count: int reference_id: typing.Optional[str] = None + logistics_entity: typing.Optional[bool] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/supply_chain/client.py b/src/sayari/supply_chain/client.py index 90dd32cd..158f43b0 100644 --- a/src/sayari/supply_chain/client.py +++ b/src/sayari/supply_chain/client.py @@ -33,6 +33,8 @@ def upstream_trade_traversal( self, id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, @@ -44,8 +46,6 @@ def upstream_trade_traversal( tier_3_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_4_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_5_shipment_country: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -62,6 +62,12 @@ def upstream_trade_traversal( id : str The root entity identifier. + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -95,12 +101,6 @@ def upstream_trade_traversal( tier_5_shipment_country : typing.Optional[typing.Sequence[Country]] Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -145,6 +145,8 @@ def upstream_trade_traversal( f"v1/supply_chain/upstream/{jsonable_encoder(id)}", method="GET", params={ + "product": product, + "-product": not_product, "risk": risk, "-risk": not_risk, "countries": countries, @@ -156,8 +158,6 @@ def upstream_trade_traversal( "tier3_shipment_country": tier_3_shipment_country, "tier4_shipment_country": tier_4_shipment_country, "tier5_shipment_country": tier_5_shipment_country, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, @@ -250,6 +250,8 @@ async def upstream_trade_traversal( self, id: str, *, + product: typing.Optional[typing.Sequence[str]] = None, + not_product: typing.Optional[typing.Sequence[str]] = None, risk: typing.Optional[typing.Sequence[Risk]] = None, not_risk: typing.Optional[typing.Sequence[Risk]] = None, countries: typing.Optional[typing.Sequence[Country]] = None, @@ -261,8 +263,6 @@ async def upstream_trade_traversal( tier_3_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_4_shipment_country: typing.Optional[typing.Sequence[Country]] = None, tier_5_shipment_country: typing.Optional[typing.Sequence[Country]] = None, - product: typing.Optional[typing.Sequence[str]] = None, - not_product: typing.Optional[typing.Sequence[str]] = None, component: typing.Optional[typing.Sequence[str]] = None, not_component: typing.Optional[typing.Sequence[str]] = None, min_date: typing.Optional[str] = None, @@ -279,6 +279,12 @@ async def upstream_trade_traversal( id : str The root entity identifier. + product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to include only trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + + not_product : typing.Optional[typing.Sequence[str]] + Product root edge filter. Filters results to exclude any trade relationships where the associated component is part of the specified product's blueprint or is a sub-component of that product. + risk : typing.Optional[typing.Sequence[Risk]] Risk leaf node filter. Only return supply chains that end with a supplier that has 1+ of the specified risk factors. @@ -312,12 +318,6 @@ async def upstream_trade_traversal( tier_5_shipment_country : typing.Optional[typing.Sequence[Country]] Filters supply chain paths where 1+ shipment country from tier 5 matches the provided values. - product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has 1+ of the specified HS codes. - - not_product : typing.Optional[typing.Sequence[str]] - Product root edge filter. Only return supply chains that start with an edge that has none of the specified HS codes. - component : typing.Optional[typing.Sequence[str]] Component edge filter. Only return supply chains that contain at least one edge with 1+ of the specified HS codes. @@ -370,6 +370,8 @@ async def main() -> None: f"v1/supply_chain/upstream/{jsonable_encoder(id)}", method="GET", params={ + "product": product, + "-product": not_product, "risk": risk, "-risk": not_risk, "countries": countries, @@ -381,8 +383,6 @@ async def main() -> None: "tier3_shipment_country": tier_3_shipment_country, "tier4_shipment_country": tier_4_shipment_country, "tier5_shipment_country": tier_5_shipment_country, - "product": product, - "-product": not_product, "component": component, "-component": not_component, "min_date": min_date, diff --git a/src/sayari/traversal/types/shortest_path_response.py b/src/sayari/traversal/types/shortest_path_response.py index c71ae635..de89c327 100644 --- a/src/sayari/traversal/types/shortest_path_response.py +++ b/src/sayari/traversal/types/shortest_path_response.py @@ -106,6 +106,7 @@ class ShortestPathResponse(UniversalBaseModel): "address": 5, }, reference_id="ecdfb3f2ecc8c3797e77d5795a8066ef/03389614/1540252800000:9030330caf25555c42c0bc0d84ea4aa1", + logistics_entity=False, ), path=[ TraversalPath( @@ -143,6 +144,7 @@ class ShortestPathResponse(UniversalBaseModel): related_entities_count=179, attribute_count={"country": 1, "address": 5, "name": 1}, reference_id="ac1fa195f9cd4ccf657bca3c6db0bb19/76232419/1717632000000:6d0f0edbd065319df4be58c3bc7909f5", + logistics_entity=False, ), relationships={ "has_lawyer": TraversalRelationshipData( diff --git a/src/sayari/traversal/types/traversal_response.py b/src/sayari/traversal/types/traversal_response.py index da85d533..65c345c9 100644 --- a/src/sayari/traversal/types/traversal_response.py +++ b/src/sayari/traversal/types/traversal_response.py @@ -90,6 +90,7 @@ class TraversalResponse(UniversalBaseModel): related_entities_count=1, attribute_count={"name": 1, "address": 2, "country": 2}, reference_id="9139b58de1bdb0157a1a1e54e56df6d3/4781466/1649116800000:0ce01cbfaa586fcfb82164f0e5a010d5", + logistics_entity=False, ), path=[ TraversalPath( @@ -137,6 +138,7 @@ class TraversalResponse(UniversalBaseModel): related_entities_count=1, attribute_count={"name": 1, "address": 2, "country": 2}, reference_id="9139b58de1bdb0157a1a1e54e56df6d3/4781466/1649116800000:0ce01cbfaa586fcfb82164f0e5a010d5", + logistics_entity=False, ), relationships={ "has_officer": TraversalRelationshipData(