Slice level with glom - glom

I have a nested structure like
target = \
{'A1':
{'B1': 'a1b1',
'B2': 'a1b2'
}
{'A2':
{'B1': 'a2b1',
'B2': 'a2b2'
}
}
how can I easily find all the items which have 'B2' in the second level (pandas terminology) i.e. ['a1b2', 'a2b2']?
I tried
glom(target, T[:, 'B2'])
glom(target, Path(Path(), Path('B2')))

I'm assuming the target you specified is a dictionary like so -
import glom
from glom import Coalesce, SKIP
target = \
{'A1':
{'B1': 'a1b1',
'B2': 'a1b2'
},
'A2':
{'B1': 'a2b1',
'B2': 'a2b2'
},
'A3':
{'B1': 'a2b1',
}
}
# We don't care about the outer key in the dictionary
# so we get only the inner dictionary by using values()
data = target.values()
# In the spec, we access the path "B2".
# Coalesce allows us to skip the item if it does not contain "B2"
spec = [Coalesce("B2",default=SKIP)]
print(list(glom.glom(data,spec)))
# ['a1b2', 'a2b2']

Related

Nested object in TOML

I have the following JSON:
{
"profile": {
"ci": {
"fuzz": {
"runs": 1000
}
}
}
}
Which I know I can write in TOML like this:
[profile.ci.fuzz]
runs = 1000
The problem is that I have multiple profiles, and writing profile.NAME.fuzz for all of them is rather repetitive.
I would like to ideally write the TOML like this:
[profile.ci]
fuzz = {
runs = 1000
}
However, that didn't work. I got this syntax error:
expected a table key, found a newline at line 2 column 9
How can I define nested objects in TOML?
TOML calls inline tables the objects defined within curly braces. Newlines are allowed for strings and arrays, but not for inline tables, from the specs:
Inline tables are intended to appear on a single line. A terminating comma (also called trailing comma) is not permitted after the last key/value pair in an inline table. No newlines are allowed between the curly braces unless they are valid within a value. Even so, it is strongly discouraged to break an inline table onto multiples lines. If you find yourself gripped with this desire, it means you should be using standard tables.
Regarding your example, this works:
[profile.ci]
fuzz = { runs = 1000 }
Something like this would also be allowed:
profiles = [
{ name = "foo", runs = 100 },
{ name = "bar", runs = 200 }
]

How to list objects in Google Cloud Storage from PHP

I am trying to list objects in a folder within a Google Cloud Storage bucket. I can get a result with 1000 objects easily (or increase the number if I want) using the following code:
$names = [];
$bucket = $client->bucket('mybucketname');
$options = ['prefix' => 'myfoldername', 'fields' =>' items/name,nextPageToken'];
$objects = $bucket->objects($options);
foreach ($objects as $object) {
$names[] = $object->name();
}
So far so good, but now I want to get the next 1000 objects (or whatever limit I set using maxResults and resultLimit) using the fact that I specified the nextPageToken object. I know that I have to do this by specifying pageToken as an option - it's just that I have no idea how.
I expect my final code will look something like this - what I need is the line of code which retrieves the next page token.
$names = [];
$bucket = $client->bucket('mybucketname');
$options = ['prefix' => 'myfoldername', 'fields' =>' items/name,nextPageToken'];
while(true) {
$objects = $bucket->objects($options);
foreach ($objects as $object) {
$names[] = $object->name();
}
$nextPageToken = $objects->getNextPageTokenSomehowOrOther(); // #todo Need help here!!!!!!!
if (empty($objects) || empty($nextPageToken)){
break;
}
$options['pageToken'] = $nextPageToken;
}
Any ideas?
The nextPageToken is the name of the last object of the first request encoded in Base64.
Here we have an example from the documentation:
{
"kind": "storage#objects",
"nextPageToken": "CgtzaGliYS0yLmpwZw==",
"items": [
objects Resource
…
]
}
If you decode the value "CgtzaGliYS0yLmpwZw==" this will reveal the value "shiba-2.jpg"
Here we have the definition of PageToken based on API documentation:
The pageToken is an encoded field that marks the name and generation of the last
object in the returned list. In a subsequent request using the pageToken, items
that come after the pageToken are shown (up to maxResults).
References:
https://cloud.google.com/storage/docs/json_api/v1/objects/list#parameters
https://cloud.google.com/storage/docs/paginate-results#rest-paginate-results
See ya

how to combine two next if together

I have a script that run on the list of files to do some of the changes, each file of them has a call event and the call event details contains 4 elements so i just want to do the changes on 2 of them only here I'm stuck with how to combine two next if in one loop, here I have used 2 loops to do the job but it takes more time , is there any idea about how to do that ?
my $calleventtag = $struct->{'transferBatch'}->{'callEventDetails'};
my #indexes = reverse (grep { exists $calleventtag->[$_]->{'supplServiceEvent'} } 0..$#$calleventtag);
my $sup_event_cnt = $#indexes;
foreach my $index (#indexes)
{
splice (#$calleventtag , $index,1);
}
foreach (0..$#$calleventtag)
{
next if ( ! exists $calleventtag->[$_]->{'mobileOriginatedCall'}) ;
if ( exists $calleventtag->[$_]->{'mobileOriginatedCall'}->{'basicCallInformation'}->{'destinationNetwork'} )
{
delete $calleventtag->[$_]->{'mobileOriginatedCall'}->{'basicCallInformation'}->{'destinationNetwork'};
}
if ( exists $calleventtag->[$_]->{'mobileOriginatedCall'}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'}
&& $calleventtag->[$_]->{'mobileOriginatedCall'}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'} !~ m/^96279/
)
{
delete $calleventtag->[$_]->{'mobileOriginatedCall'}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'};
}
}
foreach (0..$#$calleventtag)
{
next if ( ! exists $calleventtag->[$_]->{'gprsCall'});
if ( exists $calleventtag->[$_]->{'gprsCall'}->{'gprsBasicCallInformation'}->{'gprsDestination'}->{'accessPointNameOI'} )
{
delete $calleventtag->[$_]->{'gprsCall'}->{'gprsBasicCallInformation'}->{'gprsDestination'}->{'accessPointNameOI'};
}
}
for (...) {
next if ...;
...
}
can also be written as
for (...) {
if (!...) {
...
}
}
You could use the following:
use Data::Diver qw( Dive );
my $call_event_details = Dive($struct, qw( transferBatch callEventDetails ));
for my $call_event_detail (#$call_event_details) {
next if !$call_event_detail->{supplServiceEvent};
if ( my $bci = Dive($call_event_detail, qw( mobileOriginatedCall basicCallInformation )) ) {
delete $bci->{destinationNetwork};
if ( my $scs = $bci->{simChargeableSubscriber} ) {
my $msisdc = $scs->{msisdn};
delete $scs->{msisdn} if $msisdc && $msisdc !~ /^96279/;
}
}
if ( my $dest = Dive($call_event_detail, qw( gprsCall gprsBasicCallInformation gprsDestination )) ) {
delete $dest->{accessPointNameOI};
}
}
Notes:
The quotes around string literals aren't needed in hash indexes if the string is valid valid identifier. For example, $hash->{'foo'} can be written as $hash->{foo}.
-> isn't needed between two indexes. For example, $hash->{foo}->{bar} can be written as $hash->{foo}{bar}.
If a hash element is either a reference or doesn't exist, you don't need to use exists to check if you have a reference; you can use a simple truth test since references are always true.
[BUG FIX] $hash->{foo}{bar} can autovivify $hash->{foo} (cause a reference to be assigned to it), so your tests to check if stuff exists could actually be causing things to be created. To fix this, you can replace
if ($hash->{foo}{bar})
with
if ($hash->{foo} && $hash->{foo}{bar})
or
if (Dive($hash, qw( foo bar )))
Using the same long chain of indexes (->{foo}{bar}{baz}) repeatedly is error prone.
It's best to use plural names for arrays. First, it's more descriptive, but it also makes choosing names for loop variables easier.
Speaking of variable names, why would use $calleventtag for the name of the variable containing callEventDetails nodes?
You don't need to check if a hash element exists before trying to delete it; delete can be passed an element that doesn't exist.
No need to loop over the indexes of an array if you don't need the indexes.
grep was a good choice, but splice was not. You should have used: $calleventtag = [ grep { ... } #$calleventtag ];. I moved the check into the loop.

Reuse Meteor template - Isolating events

I tried:
Template.skillsSearch = $.extend Template.skillsSearch,
rendered: ->
Session.set('s' + #_id, null)
Session.set('searchFocused' + #_id, null)
#_id worked before, I think because it was inside an each statement. Now I do not have this loop and # is {}(no _id in the object).
Suppose I have this:
body
+myTemplate
+myTemplate
How could I get an unique id per template instance? Or, how can I make unique session keys when reusing a template?
This is how I solved it:
template(name='father1')
with 'father1'
+reusedTemplate
template(name='father2')
with 'father2'
+reusedTemplate
template(name='reusedTemplate')
h1 #{aVariable}
Then in coffeescript:
Template.reusedTemplate = $.extend Template.reusedTemplate,
rendered: ->
# Here #data contains whatever you pass in with
# i.e. 'father1' and 'father2' respectively
aVariable: ->
# Here # contains whatever you pass in with
# i.e. 'father1' and 'father2' respectively

Is there an easy way to add/remove/modify query parameters of a URL in Tritium?

I saw a very manual way of doing this in another post: How do I add a query parameter to a URL?
This doesn't seem very intuitive, but someone there mentioned an easier way to accomplish this using the upcoming "URL scope". Is this feature out yet, and how would I use it?
If you're using the stdlib mixer, you should be able to use the URL scope which provides helper functions for adding, viewing, editing, and removing URL params. Here's a quick example:
$original_url = "http://cuteoverload.com/2013/08/01/buttless-monkey-jams?hi=there"
$new_url = url($original_url) {
log(param("hi"))
param("hello", "world")
remove_param("hi")
}
log($new_url)
Tritium Tester example here: http://tester.tritium.io/9fcda48fa81b6e0b8700ccdda9f85612a5d7442f
Almost forgot, link to docs: http://tritium.io/current (You'll want to click on the URL category).
AFAIK, there's no built-in way of doing so.
I'll post here how I did to append a query param, making sure that it does not get duplicated if already on the url:
Inside your functions/main.ts file, you can declare:
# Adds a query parameter to the URL string in scope.
# The parameter is added as the last parameter in
# the query string.
#
# Sample use:
# $("//a[#id='my_link]") {
# attribute("href") {
# value() {
# appendQueryParameter('MVWomen', '1')
# }
# }
# }
#
# That will add MVwomen=1 to the end of the query string,
# but before any hash arguments.
# It also takes care of deciding if a ? or a #
# should be used.
#func Text.appendQueryParameter(Text %param_name, Text %param_value) {
# this beautiful regex is divided in three parts:
# 1. Get anything until a ? or # is found (or we reach the end)
# 2. Get anything until a # is found (or we reach the end - can be empty)
# 3. Get the remainder (can be empty)
replace(/^([^#\?]*)(\?[^#]*)?(#.*)?$/) {
var('query_symbol', '?')
match(%2, /^\?/) {
$query_symbol = '&'
}
# first, it checks if the %param_name with this %param_value already exists
# if so, we don't do anything
match_not(%2, concat(%param_name, '=', %param_value)) {
# We concatenate the URL until ? or # (%1),
# then the query string (%2), which can be empty or not,
# then the query symbol (either ? or &),
# then the name of the parameter we are appending,
# then an equals sign,
# then the value of the parameter we are appending
# and finally the hash fragment, which can be empty or not
set(concat(%1, %2, $query_symbol, %param_name, '=', %param_value, %3))
}
}
}
The other features you want (remove, modify) can be achieved similarly (by creating a function inside functions/main.ts and leveraging some regex magic).
Hope it helps.