Can anybody explain how sentences like this can appear in my test report?
"List(Array(109, 121, 75, 101, 121)) was not equal to List(Array(109, 121, 75, 101, 121))"
Here is the full output
Run starting. Expected test count is: 4
Ws2redisAdapterTest:
Ws2redisAdapter
- should recognize 1-arity commands
- should recognize 2-arity commands *** FAILED ***
List(Array(109, 121, 75, 101, 121)) was not equal to List(Array(109, 121, 75, 101, 121)) (Ws2redisAdapterTest.scala:15)
- should recognize N-arity commands *** FAILED ***
List(Array(109, 121, 90, 115, 101, 116), Array(48), Array(45, 49)) was not equal to List(Array(109, 121, 90, 115, 101, 116), Array(48), Array(45, 49)) (Ws2redisAdapterTest.scala:
21)
- should throw Exception if an empty string is popped
Run completed in 298 milliseconds.
Total number of tests run: 4
Suites: completed 1, aborted 0
Tests: succeeded 2, failed 2, canceled 0, ignored 0, pending 0
*** 2 TESTS FAILED ***
These are my tests in code:
package eu.codesigner.finagle.ws2redis
import org.scalatest._
class Ws2redisAdapterTest extends FlatSpec with Matchers {
"Ws2redisAdapter" should "recognize 1-arity commands " in {
val (cmd, args) = Ws2redisAdapter.adaptRedisCommand("INFO")
cmd should be("INFO")
args should be(null)
}
it should "recognize 2-arity commands " in {
val (cmd, args) = Ws2redisAdapter.adaptRedisCommand("GET myKey")
cmd should be("GET")
args should be(List("myKey".getBytes()))
}
it should "recognize N-arity commands " in {
val (cmd, args) = Ws2redisAdapter.adaptRedisCommand("ZRANGE myZset 0 -1")
cmd should be("ZRANGE")
args should be(List("myZset".getBytes(),"0".getBytes(), "-1".getBytes() ))
}
it should "throw Exception if an empty string is given" in {
a[Exception] should be thrownBy {
Ws2redisAdapter.adaptRedisCommand("")
}
}
}
Equality on arrays is only defined as reference equality (like in Java). Therefore your test fails. You can check the equality of two arrays with java.util.Arrays.equals.
Related
I am using airflow 2.2. I am trying to send multiple files using airflow email operator. the files list will be generated dynamically and using XCom pull to get the list of files from the previous task. For some reason, email operator files parameter is NOT able to read the files list from XCom value. Kindly advise.
Error details:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/airflow/task/task_runner/standard_task_runner.py", line 85, in _start_by_fork
args.func(args, dag=self.dag)
File "/usr/local/lib/python3.7/site-packages/airflow/cli/cli_parser.py", line 48, in command
return func(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/airflow/utils/cli.py", line 92, in wrapper
return f(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/airflow/cli/commands/task_command.py", line 292, in task_run
_run_task_by_selected_method(args, dag, ti)
File "/usr/local/lib/python3.7/site-packages/airflow/cli/commands/task_command.py", line 107, in _run_task_by_selected_method
_run_raw_task(args, ti)
File "/usr/local/lib/python3.7/site-packages/airflow/cli/commands/task_command.py", line 184, in _run_raw_task
error_file=args.error_file,
File "/usr/local/lib/python3.7/site-packages/airflow/utils/session.py", line 70, in wrapper
return func(*args, session=session, **kwargs)
File "/usr/local/lib/python3.7/site-packages/airflow/models/taskinstance.py", line 1332, in _run_raw_task
self._execute_task_with_callbacks(context)
File "/usr/local/lib/python3.7/site-packages/airflow/models/taskinstance.py", line 1458, in _execute_task_with_callbacks
result = self._execute_task(context, self.task)
File "/usr/local/lib/python3.7/site-packages/airflow/models/taskinstance.py", line 1514, in _execute_task
result = execute_callable(context=context)
File "/usr/local/lib/python3.7/site-packages/airflow/operators/email.py", line 88, in execute
conn_id=self.conn_id,
File "/usr/local/lib/python3.7/site-packages/airflow/utils/email.py", line 66, in send_email
**kwargs,
File "/usr/local/lib/python3.7/site-packages/airflow/utils/email.py", line 99, in send_email_smtp
mime_charset=mime_charset,
File "/usr/local/lib/python3.7/site-packages/airflow/utils/email.py", line 157, in build_mime_message
with open(fname, "rb") as file:
FileNotFoundError: [Errno 2] No such file or directory: '['
[2022-09-18, 17:24:22 UTC] {{local_task_job.py:154}} INFO - Task exited with return code 1
[2022-09-18, 17:24:23 UTC] {{local_task_job.py:264}} INFO - 0 downstream tasks scheduled from follow-on schedule check
from airflow import DAG
from airflow.operators.email import EmailOperator
from airflow.operators.python import PythonOperator
import os
from datetime import datetime, timedelta
default_args = {
"owner": 'TEST',
"depends_on_past": False,
"email_on_failure": False,
"email_on_retry": False,
"retries": 0,
}
with DAG(
dag_id="test9_email_operator_dag",
default_args=default_args,
start_date=datetime(2022, 9, 14),
end_date=datetime(2022, 9, 15),
catchup=True,
max_active_runs=1,
schedule_interval="0 12 * * *", # Runs every day # 8AM EST
) as dag:
def print_local_folder_files(local_temp_folder):
print("local folder files => ", os.listdir(local_temp_folder))
files_list = []
for file in os.listdir(local_temp_folder):
files_list.append(local_temp_folder + file)
print("files_list => ", files_list)
return files_list
print_local_folder_files = PythonOperator(
task_id='print_local_folder_files',
python_callable=print_local_folder_files,
op_kwargs={'local_temp_folder': "/usr/local/airflow/dags/temp_dir/"},
do_xcom_push=True,
provide_context=True,
dag=dag)
send_email = EmailOperator(
task_id='send_email',
to='test#gmail.com',
subject='Test Email op Notification',
html_content='Test email op notification email. ',
files="{{ task_instance.xcom_pull(task_ids='print_local_folder_files') }}"
)
print_local_folder_files >> send_email
You pushed a list to Xcom but Xcoms are rendered as string by default so what you have there is a string representation of list. This is why when you try to read it you get the first char because when you iterate over a string you get it char by char.
To solve your issue you should set render_template_as_native_obj=True on the DAG object:
with DAG(
dag_id="test9_email_operator_dag",
...,
render_template_as_native_obj=True,
) as dag:
This will let Jinja engine know that you expect to render as native Python types so you will get a list rather than a string.
For more information check Airflow docs on this feature.
For a scenario I want to check that status code of the response belongs to 200-209 or 304 or 404.
I tried the following but apparently it's not supported. And I can't find my use case in the docs.
scenario("Scenario example").exec(httpRequest
.check(status.in(200 to 209, 304, 404)))
Is there a better solution other than listing the codes manually?
.check(status.in(200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 304, 404))
.check(
status.in((200 to 209) ++ List(304, 404))
)
You passed something mixed with Seq and Int.
The method in takes Seq[Int]:
.check(
status.in((201 to 209) :+ 303 :+ 304)
)
Related: How to chain a Celery task that returns a list into a group? and Chain a celery task's results into a distributed group, but they lack a MWE, to my understanding do not fully cover my needs, and are maybe outdated.
I need to dynamically pass the output of a task to a parallel group of tasks, then pass the results of this group to a final task. I would like to make this a single "meta task".
Here's my attempt so far:
# chaintasks.py
import random
from typing import List, Iterable, Callable
from celery import Celery, signature, group, chord
app = Celery(
"chaintasks",
backend="redis://localhost:6379",
broker="pyamqp://guest#localhost//",
)
app.conf.update(task_track_started=True, result_persistent=True)
#app.task
def select_items(items: List[str]):
print("In select_items, received", items)
selection = tuple(set(random.choices(items, k=random.randint(1, len(items)))))
print("In select_items, sending", selection)
return selection
#app.task
def process_item(item: str):
print("In process_item, received", item)
return item + "_processed"
#app.task
def group_items(items: List[str]):
print("In group_items, received", items)
return ":".join(items)
#app.task
def dynamic_map_group(iterable: Iterable, callback: Callable):
# Map a callback over an iterator and return as a group
# Credit to https://stackoverflow.com/a/13569873/5902284
callback = signature(callback)
return group(callback.clone((arg,)) for arg in iterable).delay()
#app.task
def dynamic_map_chord(iterable: Iterable, callback: Callable):
callback = signature(callback)
return chord(callback.clone((arg,)) for arg in iterable).delay()
Now, to try this out, let's spin up a celery worker and use docker to for rabbitmq and redis
$ docker run -p 5672:5672 rabbitmq
$ docker run -p 6379:6379 redis
$ celery -A chaintasks:app worker -E
Now, let's try to illustrate what I need:
items = ["item1", "item2", "item3", "item4"]
print(select_items.s(items).apply_async().get())
This outputs: ['item3'], great.
meta_task1 = select_items.s(items) | dynamic_map_group.s(process_item.s())
meta_task1_result = meta_task1.apply_async().get()
print(meta_task1_result)
It gets trickier here: the output is [['b916f5d3-4367-46c5-896f-f2d2e2e59a00', None], [[['3f78d31b-e374-484e-b05b-40c7a2038081', None], None], [['bce50d49-466a-43e9-b6ad-1b78b973b50f', None], None]]].
I am not sure what the Nones, mean, but I guess the UUIDs represents the subtasks of my meta task. But how do I get their results from here?
I tried:
subtasks_ids = [i[0][0] for i in meta_task1_result[1]]
processed_items = [app.AsyncResult(i).get() for i in subtasks_ids]
but this just hangs. What am I doing wrong here? I'm expecting an output looking like ['processed_item1', 'processed_item3']
What about trying to chord the output of select_items to group_items?
meta_task2 = select_items.s(items) | dynamic_map_chord.s(group_items.s())
print(meta_task2.apply_async().get())
Ouch, this raises an AttributeError that I don't really understand.
Traceback (most recent call last):
File "chaintasks.py", line 70, in <module>
print(meta_task2.apply_async().get())
File "/site-packages/celery/result.py", line 223, in get
return self.backend.wait_for_pending(
File "/site-packages/celery/backends/asynchronous.py", line 201, in wait_for_pending
return result.maybe_throw(callback=callback, propagate=propagate)
File "/site-packages/celery/result.py", line 335, in maybe_throw
self.throw(value, self._to_remote_traceback(tb))
File "/site-packages/celery/result.py", line 328, in throw
self.on_ready.throw(*args, **kwargs)
File "/site-packages/vine/promises.py", line 234, in throw
reraise(type(exc), exc, tb)
File "/site-packages/vine/utils.py", line 30, in reraise
raise value
AttributeError: 'NoneType' object has no attribute 'clone'
Process finished with exit code 1
And finally, what I really am trying to do is something like:
ultimate_meta_task = (
select_items.s(items)
| dynamic_map_group.s(process_item.s())
| dynamic_map_chord.s(group_items.s())
)
print(ultimate_meta_task.apply_async().get())
but this leads to:
Traceback (most recent call last):
File "chaintasks.py", line 77, in <module>
print(ultimate_meta_task.apply_async().get())
File "/site-packages/celery/result.py", line 223, in get
return self.backend.wait_for_pending(
File "/site-packages/celery/backends/asynchronous.py", line 199, in wait_for_pending
for _ in self._wait_for_pending(result, **kwargs):
File "/site-packages/celery/backends/asynchronous.py", line 265, in _wait_for_pending
for _ in self.drain_events_until(
File "/site-packages/celery/backends/asynchronous.py", line 58, in drain_events_until
on_interval()
File "/site-packages/vine/promises.py", line 160, in __call__
return self.throw()
File "/site-packages/vine/promises.py", line 157, in __call__
retval = fun(*final_args, **final_kwargs)
File "/site-packages/celery/result.py", line 236, in _maybe_reraise_parent_error
node.maybe_throw()
File "/site-packages/celery/result.py", line 335, in maybe_throw
self.throw(value, self._to_remote_traceback(tb))
File "/site-packages/celery/result.py", line 328, in throw
self.on_ready.throw(*args, **kwargs)
File "/site-packages/vine/promises.py", line 234, in throw
reraise(type(exc), exc, tb)
File "/site-packages/vine/utils.py", line 30, in reraise
raise value
kombu.exceptions.EncodeError: TypeError('Object of type GroupResult is not JSON serializable')
Process finished with exit code 1
What I try to achieve here, is to get an output looking like 'processed_item1:processed_item3'. Is this even doable using celery? Any help here is appreciated.
Is there any Flutter package available that can listen for Eddystone UID beacons and Eddystone-URLs?
I have been looking at various packages such as beacons_plugin and flutter_beacon but I cannot seem to find any package that can receive these beacon broadcasts.
Has anyone been able to achieve this? If so, how?
Thank's #ukBaz - I am now seeing the Eddystone data. However i am trying to get the namespace id and instance data from the device.
I am using a Minew D15N BLE beacon and printing out the data..
I/flutter (27645): device id: AC:23:3F:6A:FE:85, name: , type: BluetoothDeviceType.le found! rssi: -68
I/flutter (27645): advertisementData => localName: , txPowerLevel: null, connectable: false
I/flutter (27645): advertisementData -> serviceUuids length: 1
I/flutter (27645): 0000feaa-0000-1000-8000-00805f9b34fb
I/flutter (27645): advertisementData -> manufacturerData length: 0
I/flutter (27645): advertisementData -> serviceData length: 1
I/flutter (27645): 0000feaa-0000-1000-8000-00805f9b34fb: [0, 232, 113, 28, 115, 246, 74, 253, 206, 7, 183, 227, 153, 153, 153, 153, 153, 153]
I sometimes also receive this..
advertisementData -> manufacturerData length: 1
I/flutter (27645): 76: [2, 21, 144, 156, 60, 249, 252, 92, 72, 65, 182, 149, 56, 9, 88, 165, 26, 90, 234, 95, 39, 15, 204]
Based on this documentation (not sure if this is right) I was trying this..
var naaa = ByteData.sublistView(manufacturerData, 2, 11);
But get this following error..
Uncaught Error: TypeError: null: type 'JSNull' is not a subtype of type 'List<int>'
Here is a screen shot of the UID slot that i have setup to test..
Those packages look like they are just for iBeacon which uses manufacturer data in the advertising packet. For Eddystone it uses service data. The flutter_blue library give you access to the service data. https://pub.dev/documentation/flutter_blue/latest/flutter_blue/AdvertisementData-class.html
The following answer shows how to scan and access the advertising data with flutter_blue: https://stackoverflow.com/a/63591662/7721752
New to software development, I'm working through Big Nerd Ranch's book 'Swift Programming'. One of the challenges set by the book is to print an array within a dictionary that contains 15 zip codes and to have them split across three lines in groups of five. The formatting must exactly match how it appears in the book.
I have tried to solve the issue using the information taught in the book with assistance from the developer documentation.
No dice.
This is what I need to print:
Caterham has the following zip codes: [111, 111, 111, 111, 111,
222, 222, 222, 222, 222,
333, 333, 333, 333, 333]
However this is the closest I can get...
var areaCodes = ["Caterham": [111, 111, 111, 111, 111], "Coulsdon": [222, 222, 222, 222, 222], "Purley": [333, 333, 333, 333, 333]]
var caterhamCodes : [Int] = []
for (_, values) in areaCodes {
caterhamCodes += values
}
print("Caterham has the following codes: \(caterhamCodes[0...4]),")
print(" \(caterhamCodes[5...9]),")
print(" \(caterhamCodes[10...14]).")
which prints:
Caterham has the following postcodes: [111, 111, 111, 111, 111],
[222, 222, 222, 222, 222],
[333, 333, 333, 333, 333].
Essentially, I need what I have above minus some square brackets and without the punctuation after each time a block of zip codes is printed. The book specifies that I might need to use a parameter called terminator. It also mentions I might need to learn how to represent special characters in string literals.
I appreciate that this is probably a high level question with a simple answer, but I'm only a few weeks into learning, so I hope I can be forgiven for asking at least a few silly questions!
Welcome to the developer community and have a nice stay!
I am trying to put answer as simple as possible, so here is my attempt:
var areaCodes = ["Caterham": [111, 111, 111, 111, 111],
"Coulsdon": [222, 222, 222, 222, 222],
"Purley": [333, 333, 333, 333, 333]]
let codesArray = areaCodes.values.sorted(by: { $0[0] < $1[0] })
let caterhamString = "Caterham has the following zip codes: ["
var printString = caterhamString
for (index, area) in codesArray.enumerated() {
for code in area {
printString += "\(code), "
}
if index != codesArray.count - 1 {
printString += "\n" + String(repeating: " ", count: caterhamString.count)
}
}
print(printString.dropLast(2).appending("]"))
Hope this helps! Good luck!
Here is a way of getting the desired output :
let intro = "Caterham has the following zip codes: ["
let spaces = ",\n" + String(repeating: " ", count: intro.count)
let areaCodes = ["Caterham": [111, 111, 111, 111, 111], "Coulsdon": [222, 222, 222, 222, 222], "Purley": [333, 333, 333, 333, 333]]
let codes = areaCodes.values.sorted { $0[0] < $1[0] }
var output = intro +
codes.map { $0.map{ String($0) }.joined(separator: ", ") }
.joined(separator: spaces)
+ "]"
print(output)
Which prints
Caterham has the following zip codes: [111, 111, 111, 111, 111,
222, 222, 222, 222, 222,
333, 333, 333, 333, 333]