I'm trying to perform a simple query with Firestore REST API.
Being on Google App Engine standard I cannot use the google-cloud-firestore client which is not yet compatible with GAE standard. Instead, I'm using google-api-python-client as for other Google APIs.
This is how I initialize my service:
service = build('firestore', 'v1beta1', credentials=_credentials)
Once this is done, I perform the query that way:
query = { "structuredQuery":
{
"from": [{ "collectionId": "mycollection" }],
"where": {
"fieldFilter":
{
"field": { "fieldPath": "myfield" },
"op": "EQUAL",
"value": { "stringValue": "myvalue" }
}
}
}
}
response = service.projects().databases().documents().runQuery(
parent='projects/myprojectid/databases/(default)/documents',
body=query).execute()
This returns an error quite explicit:
TypeError: Parameter "parent" value
"projects/myprojectid/databases/(default)/documents"
does not match the pattern
"^projects/[^/]+/databases/[^/]+/documents/[^/]+/.+$"
which obviously is true. My point is that the documentation cleary states that this should be an accepted value:
The parent resource name. In the format: projects/{project_id}/databases/{database_id}/documents or projects/{project_id}/databases/{database_id}/documents/{document_path}. For example: projects/my-project/databases/my-database/documents or projects/my-project/databases/my-database/documents/chatrooms/my-chatroom (string)
Performing the same query with the API Explorer (or curl) works fine and returns the expected results. (even though the API Explorer does state that the parent parameter does not match the expected pattern).
It seems that the discovery document (which is used by google-api-python-client) enforces this pattern check for the parent parameter but the associated regular expression does not actually allow the only parent path that seems to work (projects/myprojectid/databases/(default)/documents).
I tried to use a different pattern path like projects/myprojectid/databases/(default)/documents/*/**, which makes the query run fine but does not return any results.
Is anyone having the same issue or am I doing something wrong here ?
The only workaround I can think of is making a request directly to the proper url without using google-api-python-client, but that means that I have to handle the auth process manually which is a pain.
Thanks for any help you could provide !
google-cloud-firestore is now compatible with standard App Engine.
https://cloud.google.com/firestore/docs/quickstart-servers
for your information, a trick works.
You can change the uri after generating the request :
request = service.projects().databases().documents().runQuery(
parent='projects/myprojectid/databases/(default)/documents/*/**',
body=query)
request.uri = request.uri.replace('/*/**', '')
response = request.execute()
Related
I want to extract a workbook's currently set parameter values.
I've found reference of the desired request, as someone uses it in JS, but I can't find it anywhere in the REST API documentation, nor the documentation for tableau-api-lib nor tableauserverclient. Tableau API: Get parameter value
I can query workbooks just fine using either of the above referenced libraries, but is there a method I'm missing somewhere to get the parameter values?
Ideally I'd like to be able to modify them before a query, but getting what they're currently set at would be a nice start.
Javascript equivalent:
paramObjs = currentViz.getWorkbook().getParametersAsync();
paramObjs.then(function(paramObjs) {
for (var i = 0; i < paramObjs.length; i++) {
try {
var name = paramObjs[i].getName();
var value = paramObjs[i].getCurrentValue();
params[name] = value.value;
} catch (e) { }
}
});
From what it looks like, this task can not be done using Python.
The Workbook class here does not have any attributes/methods to get parameters
Tableau's REST API reference has no method/endpoint for that
Other API's like the Metadata and Hyper APIs have no connection/correlation with the task
A list of all Tableau packages/libraries is given here. Going through all Python libraries, there wasn't any method to fetch the parameters.
In JavaScript, they are actually creating visualizations, which allows them to query the visualization itself (currentViz.getWorkbook()). The same isn't applicable for Python I guess, which explains the missing support/APIs.
I need to fill the slot value of intent depending on some conditions.
I referred to the following documentation.
https://developer.amazon.com/en-US/docs/alexa/custom-skills/delegate-dialog-to-alexa.html#node_delegate_default_values_example
In this document, they do something like this.
// fromCity.value is empty if the user has not filled the slot. In this example,
// getUserDefaultCity() retrieves the user's default city from persistent storage.
if (!fromCity.value) {
currentIntent.slots.fromCity.value = getUserDefaultCity();
}
Similarly, I want to know to do this using the python ASK SDK. also how to return something similar to this?
// Return the Dialog.Delegate directive
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
thanks in advance!!
I finally found the solution for this.
from ask_sdk_model.dialog import delegate_directive
updateIntent = {
'name' : intent_name,
'confirmation_status' : 'NONE',
'slots' : handler_input.request_envelope.request.intent.slots
}
return handler_input.response_builder.add_directive(delegate_directive.DelegateDirective(updated_intent = updateIntent)).response
I am working on creating a new VPC where I need to provide some variables as input.
All the variables are listed in variables.tf. The file is very long (I only copied couple of them here) and variables are defined in no particular order.
I need to find a Pythonic way to sort my variables.tf by variable name.
variable "region" {
description = "The region to use when creating resources"
type = string
default = "us-east-1"
}
variable "create_vpc" {
description = "Controls if VPC should be created"
type = bool
default = true
}
variable "name" {
description = "Name to be used, no default, required"
type = string
}
The sorted variables.tf should look like this:
variable "create_vpc" {
description = "Controls if VPC should be created"
type = bool
default = true
}
variable "name" {
description = "Name to be used, no default, required"
type = string
}
variable "region" {
description = "The region to use when creating resources"
type = string
default = "us-east-1"
}
"Pythonic" might be the wrong approach here - you are still comfortably sitting behind a python interpreter, but for better or worse (worse) you are playing by Terraform's rules. Check out the links below. Hashicorp "enables" python via their CDK, and there are several other projects out there on github.
Once you are up and running with something like that, and you have Terraform fully ported over to your Python setup, then you can start thinking pythonic. </IMO>
https://github.com/hashicorp/terraform-cdk
https://github.com/beelit94/python-terraform/blob/develop/python_terraform/terraform.py
Here's what I came across last year https://github.com/hashicorp/terraform/issues/12959 and is why I created https://gist.github.com/yermulnik/7e0cf991962680d406692e1db1b551e6 out of curiosity. Not Python but awk :shrugging:
Simple awk script to sort TF files. Not just variables, but any of 1st level resource definition blocks.
I'm using the CDK to create some infrastructure from a yaml template file. Some resources require multiple instances. I thought writing a function would be the easiest way to create multiple instance of the resource
Function
def create_vpn_connection_route(cidr_count, destination_cidr):
vpn_connection_route = aws_ec2.CfnVPNConnectionRoute(
self,
f'vpn_connection_route{cidr_count}',
vpn_connection_id=vpn_connection.ref,
destination_cidr_block=destination_cidr
)
return vpn_connection_route
I then loop over it and generate the "Id" by enumarating over the destination_cidrs like so
for cidr_count, destination_cidr in enumerate(tenant_config['vpn_config'][0]['destination_cidrs']):
create_vpn_connection_route(cidr_count, destination_cidr)
This is what's in my yaml
vpn_config:
- private_ip:
- 10.1.195.201/32
- 10.1.80.20/32
- 10.1.101.8/32
Is there a better way to do this in the CDK? and can I dynamically generate Id'S for resources?
Cheers
I don't know that it makes your code much better, but you can use a Construct instead of a function.
class VpnConnectionRoute(core.Construct):
def __init__(self, scope, id_, vpn_connection, destination_cidr):
super().__init__(scope, id_)
self.vpn_connection_route = aws_ec2.CfnVPNConnectionRoute(
self,
'vpn_connection_route',
vpn_connection_id=vpn_connection.vpn_id,
destination_cidr_block=destination_cidr
)
# ...
for cidr_count, destination_cidr in enumerate(tenant_config['vpn_config'][0]['destination_cidrs']):
VpnConnectionRoute(self, f"route{cidr_count}", vpn_connection, destination_cidr)
VpnConnectionRoute(self, f"route{cidr_count}", vpn_connection, destination_cidr)
VpnConnectionRoute(self, f"route{cidr_count}", vpn_connection, destination_cidr)
CDK will automatically name your resources based on both the construct and your name. So the end result will look like:
"route1vpnconnectionrouteAE1C11A9": {
"Type": "AWS::EC2::VPNConnectionRoute",
"Properties": {
"DestinationCidrBlock": "10.1.195.201/32",
"VpnConnectionId": {
"Ref": "Vpn6F669752"
}
},
"Metadata": {
"aws:cdk:path": "app/route1/vpn_connection_route"
}
},
You can also just put destination_cidr inside your route name. CDK will remove all unsupported characters for you automatically.
for destination_cidr in tenant_config['vpn_config'][0]['destination_cidrs']:
aws_ec2.CfnVPNConnectionRoute(
self,
f'VPN Connection Route for {destination_cidr}',
vpn_connection_id=vpn_connection.vpn_id,
destination_cidr_block=destination_cidr
)
The best solution here probably depends on what you want to happen when these addresses change. For this particular resource type, any change in the name or the values will require a replacement anyway. So keeping the names consistent while the values change might not matter that much.
I have successfully created a glossary to the cloud which I can successfully list, but when trying to use it to test the translation out, I get an error:
Traceback (most recent call last):
File "C:\py\gtranstest2.py", line 57, in <module>
translate_text_with_glossary(eng,pid,gid)
File "C:\py\gtranstest2.py", line 45, in translate_text_with_glossary
response = client.translate_text(
TypeError: translate_text() got an unexpected keyword argument 'glossary_config'
My code (which is based on their example code provided here: https://cloud.google.com/translate/docs/advanced/glossary#v3):
from google.cloud import translate_v3
eng = "H1 High beam, H1 Low beam (included)"
pid = "[HIDDEN]"
def translate_text_with_glossary(
text,
project_id,
):
"""Translates a given text using a glossary."""
client = translate_v3.TranslationServiceClient()
parent = 'projects/[HIDDEN]/locations/us-central1'
glossary_config = translate_v3.types.TranslateTextGlossaryConfig(glossary="projects/[HIDDEN]/locations/us-central1/glossaries/kittglossaryv2")
# Supported language codes: https://cloud.google.com/translate/docs/languages
response = client.translate_text(
contents=[text],
target_language_code="en",
source_language_code="hu",
parent=parent,
glossary_config=glossary_config,
)
print("Translated text: \n")
for translation in response.glossary_translations:
# print(u"\t {}".format(translation.translated_text))
return translation.translated_text
translate_text_with_glossary(eng,pid)
glossary_config should be the correct argument so I don't understand the error at all. I would appreciate any help
Let me copy user Paddy Alton's answer from another question that helped me partially solve my issue:
Also encountered this. Not all the documentation has been updated yet, but they have published a migration guide:
https://googleapis.dev/python/translation/latest/UPGRADING.html
You could replace parent with "projects/<PROJECT_ID>/locations/<LOCATION>"
or define
def location_path(project_id, location):
# might as well use an f-string, the new library supports python >=3.6
return f"projects/{project_id}/locations/{location}"
and change client.location_path to location_path if this is something you use in many locations.
There are more sweeping changes, too. They now prefer you to pass a dictionary called request to the API methods, although the old way is still accepted. Thus, your code might look like this:
from google.cloud import translate_v3 as translate
client = translate.TranslationServiceClient(credentials=credentials)
response = client.translate_text(
request={
"parent": "projects/my-location/locations/global",
"target_language_code": target_language_code,
"contents": [text],
}
)
Now, you might well ask 'how will I know what to put in that request dictionary?'. It looks as though the library comes with type annotations for the dictionaries appropriate for each method: https://googleapis.dev/python/translation/latest/translate_v3/types.html
For example, I read in your comment on another answer that you have had trouble with the detect_language method. The method signature indicates that if you use keyword arguments, content should be a valid one, so I don't know why that fails - maybe it's a bug.
However, if instead you use a request dictionary, that should look like this. You'll see that the keys don't appear to correspond exactly to the method signature keywords (although content is one of them).
This code would work:
response = client.detect_language({
"parent": "projects/my-location/locations/global",
"content": "Tá Gaeilge Agam, ach tá mé i mo chonai i Sasana",
})
lang = response.languages[0].language_code
(the return type is somewhat convoluted, as you can see)
Now after changing the code like this:
response = client.translate_text(
request={
"contents": [text],
"source_language_code": "en",
"target_language_code": "hu",
"parent": parent,
"glossary_config": glossary_config,
}
)
I get no glossary_config error and the code returns a translation. My only problem is now that the result translation I get doesn't seem to use my provided glossary even though it says it does. But this probably should be another thread.
I've checked your code with my experimental data, modifying a bit parent and glossary_config argument definitions entire translate_text() method referring to the example from documentation, translate_text_with_glossary() function works as intended.
client = translate_v3.TranslationServiceClient()
parent = client.location_path("Project_ID", "us-central1")
glossary = client.glossary_path("Project_ID", "us-central1", "Glossary-ID")
glossary_config = translate_v3.types.TranslateTextGlossaryConfig(glossary=glossary)
Please keep in mind that sharing personal identifiable information such as unique account identifiers within either code examples or the question description may significantly increase a risk of harmful events compromising customer computation resources.