I'm on my way to simplify a set of tests by pytest by stacking parameters
import pytest
#pytest.mark.parametrize("option_a", ["-r", "-s"])
#pytest.mark.parametrize("option_b", ["--alpha", "--beta", "--gamma"])
def test_foo(option_a, option_b):
assert option_a in ["-r", "-s"]
As anticipated, the above MWE performs an exhaustive permutation:
======================================= test session starts =======================================
platform linux -- Python 3.9.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/guest/Desktop/project, configfile: pytest.ini
collected 6 items
test_ping.py::test_foo[--alpha--r] PASSED [ 16%]
test_ping.py::test_foo[--alpha--s] PASSED [ 33%]
test_ping.py::test_foo[--beta--r] PASSED [ 50%]
test_ping.py::test_foo[--beta--s] PASSED [ 66%]
test_ping.py::test_foo[--gamma--r] PASSED [ 83%]
test_ping.py::test_foo[--gamma--s] PASSED [100%]
======================================== 6 passed in 0.02s ========================================
What bothers me a bit is the additional dash trailing the first parameter (--alpha, --beta, --gamma). Someone not familiar enough with pytest may assume the second parameter tested would be --r (instead of -r), or --s (instead of -s).
Is there a practical approach to substitute this separator by a blank space? Since this is just an issue how output to the CLI is formatted, I would like to refrain to define multiple fixtures for each test function.
To summarize our comments, it's possible to use ids and keep in mind test ordering. pytest is going to use the parameter with the higher number of levels as an outer loop (here: option_b), the one with fewer levels as the inner one (here: option_a). Also, I have added the custom_format function as an example of an approach how to custom a view of a parameter.
import pytest
#pytest.mark.parametrize("option_a", ["-r", "-s"], ids=[" -r", " -s"])
#pytest.mark.parametrize("option_b", ["--alpha", "--beta", "--gamma"], ids=["--alpha ", "--beta ", "--gamma "])
def test_foo(option_a, option_b):
assert option_a in ["-r", "-s"]
def custom_format(val):
return f" {val} "
#pytest.mark.parametrize("option_a", ["-r", "-s"], ids=custom_format)
#pytest.mark.parametrize("option_b", ["--alpha", "--beta", "--gamma"], ids=custom_format)
def test_foo_1(option_a, option_b):
assert option_a in ["-r", "-s"]
It will not remove hyphens between parameters but could decrease confusion.
collected 12 items
test_.py::test_foo[--alpha - -r] PASSED [ 8%]
test_.py::test_foo[--alpha - -s] PASSED [ 16%]
test_.py::test_foo[--beta - -r] PASSED [ 25%]
test_.py::test_foo[--beta - -s] PASSED [ 33%]
test_.py::test_foo[--gamma - -r] PASSED [ 41%]
test_.py::test_foo[--gamma - -s] PASSED [ 50%]
test_.py::test_foo_1[ --alpha - -r ] PASSED [ 58%]
test_.py::test_foo_1[ --alpha - -s ] PASSED [ 66%]
test_.py::test_foo_1[ --beta - -r ] PASSED [ 75%]
test_.py::test_foo_1[ --beta - -s ] PASSED [ 83%]
test_.py::test_foo_1[ --gamma - -r ] PASSED [ 91%]
test_.py::test_foo_1[ --gamma - -s ] PASSED [100%]
Related
May I ask is it possible in groovy to transform the map recursively by removing all the key and only keep the value for maps with certain key prefix (e.g. pk-).
Example from this:
[
applications:[
pk-name-AppA:[name:AppA, keyA1:valueA1Prod, keyA2:valueA2],
pk-name-AppB:[name:AppB, keyB1:valueB1Prod, keyB2:valueB2],
otherAppC:[name:AppC, keyA1:valueA1Prod, keyA2:valueA2]
]
]
to
[
applications:[
[name:AppA, keyA1:valueA1Prod, keyA2:valueA2],
[name:AppB, keyB1:valueB1Prod, keyB2:valueB2],
otherAppC:[name:AppC, keyA1:valueA1Prod, keyA2:valueA2]
]
]
I'm processing through Telegram history (txt file) and I need to extract & process quite complex (nested) multiline pattern.
Here's the whole pattern
Free_Trade_Calls__AltSignals:IOC/ BTC (bittrex)
BUY : 0.00164
SELL :
TARGET 1 : 0.00180
TARGET 2 : 0.00205
TARGET 3 : 0.00240
STOP LOS : 0.000120
2018-04-19 15:46:57 Free_Trade_Calls__AltSignals:TARGET
basically I am looking for a pattern starting with
Free_Trade_Calls__AltSignals: ^%(
and ending with a timestamp.
Inside that pattern (telegram message)
- exchange - in brackets in the 1st line
- extract value after BUY
- SELL values in a array of 3 SELL[3] : target 1-3
- STOP loss value (it can be either STOP, STOP LOSS, STOP LOS)....
I've found this Logstash grok multiline message but I am very new to logstash firend advised it to me. I was trying to parse this text in NodeJS but it really is pain in the ass and mad about it.
Thanks Rob :)
Since you need to grab values from each line, you don't need to use multi-line modifier. You can skip empty line with %{SPACE} character.
For your given log, this pattern can be used,
Free_Trade_Calls__AltSignals:.*\(%{WORD:exchange}\)\s*BUY\s*:\s*%{NUMBER:BUY}\s*SELL :\s*TARGET 1\s*:\s*%{NUMBER:TARGET_1}\s*TARGET 2\s*:\s*%{NUMBER:TARGET_2}\s*TARGET 3\s*:\s*%{NUMBER:TARGET_3}\s*.*:\s*%{NUMBER:StopLoss}
please note that \s* equals to %{SPACE}
It will output,
{
"exchange": [
[
"bittrex"
]
],
"BUY": [
[
"0.00164"
]
],
"BASE10NUM": [
[
"0.00164",
"0.00180",
"0.00205",
"0.00240",
"0.000120"
]
],
"TARGET_1": [
[
"0.00180"
]
],
"TARGET_2": [
[
"0.00205"
]
],
"TARGET_3": [
[
"0.00240"
]
],
"StopLoss": [
[
"0.000120"
]
]
}
I have a *.csv file that store two columns of float data.
I am using this function to import it but it generates the data not separated with comma.
data=np.genfromtxt("data.csv", delimiter=',', dtype=float)
output:
[[ 403.14915 150.560364 ]
[ 403.7822265 135.13165 ]
[ 404.5017 163.4669 ]
[ 434.02465 168.023224 ]
[ 373.7655 177.904114 ]
[ 450.608429 208.4187315]
[ 454.39475 239.9666595]
[ 453.8055 248.4082 ]
[ 457.5625305 247.70315 ]
[ 451.729431 258.19335 ]
[ 366.74405 225.169922 ]
[ 377.0055235 258.110077 ]
[ 380.3581 261.760071 ]
[ 383.98615 262.33805 ]
[ 388.2516785 272.715332 ]
[ 408.378174 200.9713135]]
How to format it to get a numpy array like
[[ 403.14915, 150.560364 ]
[ 403.7822265, 135.13165 ],....]
?
NumPy doesn't display commas when you print arrays. If you really want to see them, you can use
print(repr(data))
The repr function forces a str representation not ment for "nice" printing, but for the literal representation you would use yourself to type the data in your code.
Trying to get some of my old code up and running in Pharo. Some method names are different but after some hardship I managed to find equivalents that work.
I am parsing my code and I'd like to check if the receiver or any of the arguments is aSymbol in an effort to match them to supported alternatives. I've managed to do this to selectors, by analysing RBMessageNode s
aNode selector == aSymbol ifTrue: [ aNode selector: replacementSymbol ].
How can this be done to arguments and receivers? Is there a comprehensive guide on RBParser somewhere?
By direct manipulation
Assuming that you are looking for cases like this:
aSymbol message: aSymbol message: aSymbol
For receiver you should do:
(aNode isMessage and: [
aNode receiver isVariable and: [
aNode receiver name = 'aSymbol' ]]) ifTrue: [
"do your job here" ]
Here is another example on how to replace #aSymbol arguments with #newSymbol:
messageNode arguments: (messageNode arguments collect: [ :arg |
(arg isLiteralNode and: [ arg value = #aSymbol ])
ifFalse: [ arg ]
ifTrue: [ | newNode |
newNode := #aNewSymbol asLiteralNode.
arg replaceSourceWith: newNode.
newNode ] ]).
methodClass compile: ast newSource
The replaceSourceWith: makes sure that just a source will be replaced, but for newSource to actually return a new source you also need to swap the nodes themselves, that's why I'm doing a collect on arguments and return the new ones where needed.
You can view help about RBParser in Word Menu > Help > Help Browser > Refactoring Framework.
You can also play around by inspecting
RBParser parseExpression: 'aSymbol message: aSymbol message: aSymbol'
and looking at its contents
By Parse Tree Transformation
You can use pattern code to match and replace certain code. For example to change the symbol argument of a perform: message you can do this:
ast := yourMethod parseTree.
rewriter := RBParseTreeRewriter new
replace: '`receiver perform: #aSymbol'
with: '`receiver perform: #newSelector'.
(rewriter executeTree: ast) ifTrue: [
yourMethod class compile: ast newSource ]
You can learn more about the pattern matching syntax in the help topic Word Menu > Help > Help Browser > Refactoring Framework > Refactoring Engine > RBPatternParser …. I thing that MatchTool from pharo catalog can greatly help you in testing the match expressions (it also has a dedicated help topic about the matching syntax) while RewriteTool can help you to preview how your code will be transformed.
I wish to generate a lot of --enable-*/--disable-* options by something like:
COMPONENTS([a b c], [yes])
where the second argument is the default value of the automatic enable_* variable. My first attempt was to write an AC_ARG_ENABLE(...) within an m4_foreach_w, but so far, I'm only getting the first component to appear in the ./configure --help output.
If I add hand-written AC_ARG_ENABLEs, they work as usual.
Regardless, the --enable-*/--disable-* options work as they should, just the help text is missing.
Here's the full code to reproduce the problem:
AC_INIT([foo], 1.0)
AM_INIT_AUTOMAKE([foreign])
AC_DEFUN([COMPONENTS],
[
m4_foreach_w([component], [$1], [
AS_ECHO(["Processing [component] component with default enable=$2"])
AC_ARG_ENABLE([component],
[AS_HELP_STRING([--enable-[]component], [component] component)],
,
[enable_[]AS_TR_SH([component])=$2]
)
])
AC_ARG_ENABLE([x],
[AS_HELP_STRING([--enable-[]x], [component x])],
,
[enable_[]AS_TR_SH([x])=$2]
)
AC_ARG_ENABLE([y],
[AS_HELP_STRING([--enable-[]y], [component y])],
,
[enable_[]AS_TR_SH([y])=$2]
)
])
COMPONENTS([a b c], [yes])
for var in a b c x y; do
echo -n "\$enable_$var="
eval echo "\$enable_$var"
done
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
And an empty Makefile.am. To verify that the options work:
$ ./configure --disable-a --disable-b --disable-d --disable-x
configure: WARNING: unrecognized options: --disable-d
...
Processing component a with default enable=yes
Processing component b with default enable=yes
Processing component c with default enable=yes
$enable_a=no
$enable_b=no
$enable_c=yes
$enable_x=no
$enable_y=yes
After I poked around in autoconf sources, I figured out this has to do with the m4_divert_once call in the implementation of AC_ARG_ENABLE:
# AC_ARG_ENABLE(FEATURE, HELP-STRING, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
# ------------------------------------------------------------------------
AC_DEFUN([AC_ARG_ENABLE],
[AC_PROVIDE_IFELSE([AC_PRESERVE_HELP_ORDER],
[],
[m4_divert_once([HELP_ENABLE], [[
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]]])])dnl
m4_divert_once([HELP_ENABLE], [$2])dnl
_AC_ENABLE_IF([enable], [$1], [$3], [$4])dnl
])# AC_ARG_ENABLE
# m4_divert_once(DIVERSION-NAME, CONTENT)
# ---------------------------------------
# Output CONTENT into DIVERSION-NAME once, if not already there.
# An end of line is appended for free to CONTENT.
m4_define([m4_divert_once],
[m4_expand_once([m4_divert_text([$1], [$2])])])
I'm guessing that the HELP-STRING argument is remembered in it's unexpanded form, so it is added just once for all components. Manually expanding the AC_HELP_STRING does what I want:
AC_DEFUN([COMPONENTS],
[
m4_foreach_w([comp], [$1], [
AS_ECHO(["Processing component 'comp' with default enable=$2"])
AC_ARG_ENABLE([comp],
m4_expand([AS_HELP_STRING([--enable-comp], enable component comp)]),
,
[enable_[]AS_TR_SH([comp])=$2]
)
])
])
COMPONENTS([a b c x y], [yes])
I couldn't find a way to properly quote components so that it appears as a string, after being used as the loop variable in m4_foreach_w, so I just renamed it to spare me the trouble.