How do I create a `CfnOutput` that is a list of values? - aws-cdk

All of the examples use the CfnOutput class. But the CfnOutput class only accepts a str for the value parameter.
This doesn't work for that reason:
from aws_cdk import CfnOutput, Stack, aws_ec2
from constructs import Construct
class MyVpc(Stack):
def __init__(self, scope: Construct, construct_id: str) -> None:
super().__init__(scope, construct_id)
vpc = aws_ec2.Vpc.from_lookup(scope, construct_id, is_default=True)
CfnOutput(self, "private_subnets", values=vpc.private_subnets)
CfnOutput(self, "public_subnets", values=vpc.public_subnets)
The error being
Argument of type "List[ISubnet]" cannot be assigned to parameter "value" of type "str" in function
As the code snippet shows, I'd like to export a list of VPC subnets from the AWS-created default VPC in order to pass into to an another stack that needs a list of subnet IDs. There is no example or documentation for something like this that I can find after a long search in vain: there are hundreds of Python classes in this library whose documentation is extremely difficult to navigate for someone who's new to AWS CDK. I can concatenate the subnet IDs into a string and then split them in the other stack, but that seems ridiculous.
What is the correct way to export a value that is more general than a string from one stack to be used in another stack?

You can't output a list, only strings, I would iterate over the vpc.private_subnets
for idx, subnet in vpc.private_subnets:
CfnOutput(self, f"private_subnet{idx}", values=subnet)
You mentioned you want to use this in another stack. If you implementing nested stacks I would,'t use this approach as you can just pass the Vpc object into your nested stacks so
compute_stack = ComputeStack(self, "ComputeStack", vpc=vpc_stack.vpc) and then call ec2.SubnetSelection
If you're set on using outputs and want to reference them in other stacks look at using from_look_up

Related

The argument type 'ListOf5' can't be assigned to the parameter type 'ListOf5'

I need to implement an abstract class function, which own a an specific data type. But I need inside my logic layer to make the attribute which is going to be passed as a dynamic data type. But when i Pass it to the function, i am sure that its data type will be as needed. So, i type (product.value.pickedImages) as ListOf5) . But it does an Exception.
The Abstract Class Code Is:
Future<Either<FireStoreServerFailures, List<String>>> uploadProductImages(
{required ListOf5<File> images});
The Implementation Code Is:
Future<Option<List<String>>> _uploadImagesToFirestorage() async {
return await productRepo
.uploadProductImages(
images: (product.value.pickedImages) as ListOf5<File>) // Exception
}
The Exception Is:
The argument type 'ListOf5 < dynamic>' can't be assigned to the
parameter type 'ListOf5 < File>'.
You are trying to cast the List from List<dynamic> to List<String>.
Instead, you should cast each item, using something like this:
void main() {
List<dynamic> a = ['qwerty'];
print(List<String>.from(a));
}
Not sure about the implementation of this ListOf5 though...
The cast (product.value.pickedImages) as ListOf5<File> fails.
It fails because product.value.pickedImages is-not-a ListOf5<File>, but instead of ListOf5<dynamic> (which may or may not currently contain only File objects, but that's not what's being checked).
Unlike a language like Java, Dart retains the type arguments at run-time(it doesn't do "erasure"), so a ListOf5<dynamic> which contains only File objects is really different from a ListOf5<File> at run-time.
You need to convert the ListOf5<dynamic> to a ListOf5<File>.
How to do that depends on the type ListOf5, which I don't know.
For a normal List, the two most common options are:
(product.value.pickedImages).cast<File>(). Wraps the existing list and checks on each read that you really do read a File. It throws if you ever read a non-File from the original list. Perfectly fine if you'll only read the list once.
List<File>.of(product.value.pickedImages). Creates a new List<File> containing the values of product.value.pickedImages, and throws if any of the values are not File objects. Requires more memory (because it copies the list), but fails early in case there is a problem, and for small lists, the overhead is unlikely to be significant. If you read the resulting list many times, it'll probably be more efficient overall.
If the ListOf5 class provides similar options, you can use those. If not, you might have to build a new ListOf5 manually, casting each element of the existing ListOf5<dynamic> yourself.
(If the ListOf5 class is your own, you can choose to add such functionality to the class).

Instantiating a class by String name in Dart

I am trying to call a method of a class that I only know by name as a String. Now therefore I would need a ClassMirror of that class that allowes me to instantiate an instance. However, creating ClassMirrors seems to be only possible by entering a type using reflectClass(Type) or by passing an already existing instance of that class into reflect(dynamic). So these aren`t helping if I only have a String.
In Java you can do this pretty easily, by calling Class.forName(String). Then you would get a Constructor instance, make it accessibly and call it.
Does anyone know if this is even possible in dart? What seems weird is that once you have a ClassMirror you can access fields and methods by passing symbols, which can be created by Strings.
You can put a specific list of strings to map to a specific list of closures to create a new object with specific parameters.
But you can't get a reflection without using dart:mirrors, which is being deprecated, and also had a negative impact on tree shaking to get the payload size down.
In general, you're invited to look at the package:reflectable to achieve most of what you'd want out of dart:mirrors, using source-to-source builders.

Is there a way to import (open) specific functions in F#?

Instead of importing a whole module, is there a way to open specific functions in another module? Something like:
open TestFuncs with [myTestFuncInOtherModule]
As you can see in the docs, the open keyword doesn't actually load a module or namespace. It just allows you to refer to elements in that module/namespace without refering to their fully qualified name.
Being so, when you use open you're just making it easier to call the functions in that module, not actually importing/loading them in memory, so the short answer for this question is that using the open keyword you can't do this to only one function.
You can achieve the same thing easily with a let binding, though:
let f = TestFuncs.myTestFuncInOtherModule
It's not currently possible, but I've actually put in a request for this to be added to the language. If you want to see this added in F# 4.0, one thing you could do is go vote for that request.
Another good workaround, that hasn't been mentioned yet by other answers, is to "pseudo-open" modules: assign a short name to modules whose contents you want to use. Like so:
module TP = Microsoft.FSharp.Data.TypeProviders
type mySchema = TP.SqlDataConnection<"...">
let db = mySchema.GetDataContext()
This gives you the convenience of not having to type the whole module name every time you want to reference its contents, but you maintain control of your namespace: this way there's no chance of accidental name collisions when you update a module to a new version and it adds new names.
You can refer to particular functions in another module using full function name ModuleName.funcName:
module One =
let square x = x * x
module Two =
let anothersquare x = One.square x

Request linking of a specific node in xText

In my DSL I have a cunstruct such as:
myInstance.abc == 2 -> [...]
template myTemplate
const int abc;
endtemplate
instance myInstance of myTemplate with abc:=2;
The creation of instances can be anywhere in the code since instances are static and won't change. Ever. So I want the placement of instances in the code to not matter.
But during scoping the first line will be served first so in order to do so I need myInstance to be linked to myTemplate beforehand. But the linking hasn't reached that part of the code yet. Is there a way to request linking of a specific node from within my custom ScopeProvider?
EDIT:
Something such as
SomeLibrary.ensureLinked((EObject)templateInstance);
In your scope provider you have access to the whole DOM. So just scan the DOM for all occurrences of "instance" and provide these as scope. You are not limited to the element given as parameter to your scope provider, but you can navigate the DOM to any element reachable.
The scope provider usually returns all elements applicable for the current scope. xText then by their name. So you usually define scope providers for whole blocks, not for each element inside a block. In the implementation you have to navigate through the DOM part representing your block.

How to initialize global variables in TurboGears 2 with values from a table

I need a global variable that I can call from the templates.
I edited app_globals.py in lib directory to declare PATH_TO_IMAGES like this
class Globals(object):
"""Container for objects available throughout the life of the application.
One instance of Globals is created during application initialization and
is available during requests via the 'app_globals' variable.
"""
PATH_TO_IMAGES = ""
def __init__(self):
"""Do nothing, by default."""
pass
Now I can call from any template the image path like this
<img src="${g.PATH_TO_IMAGES}/${p.image}" />
The image path is stored inside a settings table on the app's database, but I can't initialize it from Globals declaration, i get this error:
sqlalchemy.exc.UnboundExecutionError:
Could not locate a bind configured on
mapper
Mapper|Settings|settings,
SQL expression or this Session
My guess is that database binding happens after Globals is initialized. So my questions is, which is the best place to initialize a global variable in TurboGears 2 and which is the best practice to that.
Just use a cached property:
class Globals(object):
"""Container for objects available throughout the life of the application.
One instance of Globals is created during application initialization and
is available during requests via the 'app_globals' variable.
"""
#property
def PATH_TO_IMAGES(self):
try:
return self._path_to_images
except AttributeError:
self._path_to_images = db_session.query(XXX) # Fill in your query here
return self._path_to_images
PS : your question is a generic Python question really. I suggest you read the official Python docs before posting other similar questions.
You probably need to create your own database connection to get this data from the database.
In SQLAlchemy terms, you'll want to create your own engine, session, etc. Just make sure to clean up after you're done.
I would probably do this in app_cfg.py using on_startup to get it into the config, and then stick it in the Globals object later on if you still need to.
You may set PATH_TO_IMAGES to it's definite value once the models are initialized. The sooner being at the end of the 'init_model' function declared in model/init.py.

Resources