Python Forum
mutable values to string items? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: mutable values to string items? (/thread-38016.html)

Pages: 1 2


mutable values to string items? - fozz - Aug-21-2022

Hi,
I've got the next list:
channels = [
    [ '#channel1', 0 ],
    [ '#channel2', 0 ],
    [ '#channel3', 0 ]
]
I can change the values for each channel like:
channel1[1] = somevalue
channel2[1] = somevalue
channel3[1] = anothervalue
That is working oke.
The problem is, the script is changed and now it uses a string like:
net.ipv6 "#channel1,#channel2,#channel3"
I can call each channel separtly by:
for channel in channels.split(',')
No problem for this part.
The big question is: How can i add the mutable values for each item (channel) in this string?


RE: mutable values to string items? - snippsat - Aug-21-2022

Maybe a dictionary would work,but not sure what task you try to solve with it.
>>> ch = "#channel1,#channel2,#channel3"
>>> ch = ch.split(',')
>>> ch
['#channel1', '#channel2', '#channel3']

>>> values = (1, 42, 'spam')
>>> d = dict(zip(ch, values))
>>> d
{'#channel1': 1, '#channel2': 42, '#channel3': 'spam'}
>>> d['#channel2'] = 100
>>> d
{'#channel1': 1, '#channel2': 100, '#channel3': 'spam'}

>>> d.get('#channel3', 'No channel found')
'spam'
>>> d.get('#channel4', 'No channel found')
'No channel found'



RE: mutable values to string items? - rob101 - Aug-21-2022

Does this do what you have in mind?

x = "#channel1,#channel2,#channel3"
x_list = []
x_string = ''

for item in x:
    x_string += item
    if item == ',':
        x_list.append(x_string)
        x_list.append(0)
        x_string = ''
x_list.append(x_string)
x_list.append(0)

print(x_list)
Output:
['#channel1,', 0, '#channel2,', 0, '#channel3', 0]



RE: mutable values to string items? - deanhystad - Aug-22-2022

I'm really confused because this:
channels = [
    [ '#channel1', 0 ],
    [ '#channel2', 0 ],
    [ '#channel3', 0 ]
Does not appear to have anything in common with this:
channel1[1] = somevalue
channel2[1] = somevalue
channel3[1] = anothervalue
What are you starting with, and how do you want it to look after it has been processed?


RE: mutable values to string items? - DeaD_EyE - Aug-22-2022

(Aug-21-2022, 08:06 PM)fozz Wrote:
channels = [
    ['#channel1', 0],
    ['#channel2', 0],
    ['#channel3', 0],
]

Assigning the first element from channels to a name:
first = channels[0]
Assigning a list to the first element of the list channels:
channels[0] = ["channel33", 33]
If you do not want to use integer indices, then use a dict.
channels = {
    '#channel1': 0,
    '#channel2': 0,
    '#channel3': 0,
}

channels['#channel4'] = 33
channels['#channel1'] = 1

for name, value in channels.items():
    print(name, "->", value)
Output:
#channel1 -> 1 #channel2 -> 0 #channel3 -> 0 #channel4 -> 33
Getting all values, but not the channels (keys of the dict):
print(list(channels.values()))
Output:
[1, 0, 0, 33]
If you use for your program the wrong data structures, then handling the data is very complicated.


RE: mutable values to string items? - fozz - Aug-22-2022

Thank you for the help guys, but like i said in the first post, that is the old situation, maybe I wasn't clear.
The goal is to make a channel limiter for irc channels (protection against mass joins) and make it work for more channels ,in the old script it worked flawless on multiple channels because of the list, in the new situation the script works, but only on one channel, if I add more then one channel in the string of the script the timer keeps on looping because the script cannot determine which value for what channel, so my idea was to add a value (the setted limit on the channel) to an item(channel) of the string.
Maybe it's better to post the old and new scripts to clarify it:
OLD situation:
from weechat import (
    WEECHAT_RC_OK, info_get, prnt, register, 
    string_eval_expression, command, hook_timer)

NAME = 'Limiter'
AUTHOR = 'fozz <fozz@someone>'
VERSION = '0.1'
LICENSE = 'GPL3'
DESCRIPTION = 'Channel limiter, protection against mass joining from clones/botnets'

register(NAME, AUTHOR, VERSION, LICENSE, DESCRIPTION, '', '')

# Configuration 
limit_ = 5
min_offset_ = 2 #lowest diff
max_offset_ = 2 #highest diff
interval_ = 3
network_ = 'ircnet'
channels_ = [
    [ '#python', 0 ],
    [ '#forum', 0 ]
]

def limiter_cb(data, signal):

    global limit_, min_offset_, max_offset_, network_, channels_

    for channel in channels_:
        
        buffer = info_get('irc_buffer', network_+',' + channel[0])
        nc = int(string_eval_expression('${buffer.nicklist_visible_count}', {'buffer': buffer}, {}, {}))
        nl = nc + limit_
        minoff = nl - min_offset_
        maxoff = nl + max_offset_

        if  channel[1] <= minoff or channel[1] >= maxoff:
            command(buffer, '/mode ' + channel[0] + ' +l ' + f'{nl}')
            channel[1] = nl

    return WEECHAT_RC_OK

hook_timer(interval_ * 60000, 0, 0, 'limiter_cb', '')
To be clear, the above script worked as it should (on multiple channels).
Now the new situation (is running also on more then one channel so that part is ok) but keeps on looping and setting the limit on the channel again and again (one channel added in the string is no problem)
# Simple Channel limiter version 0.1.
# Protection script against mass joining from clones/botnets on your channel.

''' /set plugins.var.python.limiter.limiter_chans.ircnet #python,#forum '''

from weechat import (
    WEECHAT_RC_OK, register, infolist_get, infolist_string, buffer_search,
    config_get_plugin, infolist_next, string_eval_expression, command, hook_timer, infolist_free)

NAME = 'limiter'
AUTHOR = 'fozz <[email protected]>'
VERSION = '0.1'
LICENSE = 'GPL3'
DESCRIPTION = 'Channel limiter, protection against mass joining from clones/botnets'

register(NAME, AUTHOR, VERSION, LICENSE, DESCRIPTION, '', '')

# Configuration 
limit_ = 5
min_offset_ = 2 #lowest diff
max_offset_ = 2 #highest diff
interval_ = 1

offset_ = int()

def limiter_cb(data, signal):

    global limit_, min_offset_, offset_, max_offset_

    networks = infolist_get('irc_server', '', '')
    while infolist_next(networks):
        network = infolist_string(networks, 'name')
        channels = config_get_plugin('limiter_chans.{}'.format(network))
        if channels:
            
            for channel in channels.split(','):
                buffer = buffer_search('irc', '{}.{}'.format(network, channel))
                if buffer:

                   nc = int(string_eval_expression('${buffer.nicklist_visible_count}', {'buffer': buffer}, {}, {}))
                   nl = nc + limit_ 
                   minoff = nl - min_offset_
                   maxoff = nl + max_offset_
                        
                   if  offset_ <= minoff or offset_ >= maxoff:
                       command(buffer, '/mode ' + channel + ' +l ' + f'{nl}')
                            
                       offset_ = nl

    infolist_free(networks)

    return WEECHAT_RC_OK

hook_timer(interval_ * 60000, 0, 0, 'limiter_cb', '')
Any help is very welcome, I stumbled upon setting the data for each channel separtly from the string to nest, that's why the idea with a list from the old situation or something.
The string is like this in the new situation:
limiter_chans.ircnet "#python,#forum"


RE: mutable values to string items? - fozz - Aug-29-2022

Any help please,
How can i write the channels found in the next string:
plugins.var.python.limiter.limiter_chans.ircnet #python,#forum
to a file (maybe using pandas or csv) and can read the data (the limit for the specific channel) back?
i can retrieve the setted channels with:
channels = config_get_plugin('limiter_chans.{}'.format(network))
The goal is that i don't have edit that file manually, so the only setting i change in the program is with:
/set plugins.var.python.limiter.limiter_chans.ircnet #python,#forum
It should look something like this in the file i guess
channels_ = [[ '#python', 0 ], [ '#forum', 0 ]]
Or:
channel | limit
#python | 45
#forum  | 64
(the #channels and llimits (45 and 64 in this example) should be modified by the script)


RE: mutable values to string items? - Gribouillis - Aug-29-2022

Here is code to store the list in a csv file and read it back. Hope it helps
import csv
import io
from pathlib import Path

source = "plugins.var.python.limiter.limiter_chans.ircnet #python,#forum"

# extract the list ['#python', '#forum']
ichan = [x.strip() for x in source.split(' ', 1)[1].strip().split(',')]

# create the list [["#python#, 0], ['#forum', 0]]
channels = [[x, 0] for x in ichan]

# serialize channels as csv content
ofh = io.StringIO()
csv.writer(ofh).writerows(channels)
content = ofh.getvalue()

# optional: save content to file
filename = Path(__file__).parent/'channels.csv'
filename.write_text(content)

# optional: read file to get content
content = filename.read_text()

# deserialize content as a list of list
channels = [[chan, int(num)] for (chan, num) in csv.reader(io.StringIO(content))]
print(channels) # prints [['#python', 0], ['#forum', 0]]



RE: mutable values to string items? - deanhystad - Aug-29-2022

Why do you suddenly need a file? Before you had a list that contained this information. Why can't you still use a list (or a dictionary)?

What string are you talking about here?
Quote:The string is like this in the new situation:
limiter_chans.ircnet "#python,#forum"
What command in your program is returning this string? Or are you trying to generate a string like this? Assume that I know nothing about weechat. I think that is mostly true for most of the people on the forum. A search for weechat only found posts in this thread and your other thread "Matching multiple parts in string". No results at all for "wechat"


RE: mutable values to string items? - fozz - Aug-29-2022

Thank you for this Gribouillis, i will try that tomorrow.
Quote:Why do you suddenly need a file? Before you had a list that contained this information. Why can't you still use a list (or a dictionary)?