FAQ
Trying to add the current filename into the existent 'downloads' column
Somehow i don't think i just use the plus sign into an existing column.
We don't try to add numbers here but add an extra string to an already
existing array of strings(list).


======================================================
# update specific torrent's download counter
cur.execute('''UPDATE files SET hits = hits + 1, host = %s, city = %s,
lastvisit = %s WHERE torrent = %s''', (host, city, lastvisit, filename) )


# update specific visitor's download record
cur.execute('''UPDATE visitors SET downloads = downloads + %s WHERE host
= %s''', (filename, host) )
======================================================








Retrieval time for displaying purposes:
======================================================
downloads = []
if cur.rowcount:
  for torrent in data:
   downloads = ', '.join( torrent )
  else:
   downloads = '?????? ????????? ???????'


# add this visitor entry into database (visits is unique)
cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
useros, browser, visits, downloads) VALUES (%s, %s, %s, %s, %s, %s, %s,
%s)''', (cID, refs, host, city, useros, browser, visits, downloads) )
======================================================


Is this correct, personally i would just prefer:


for torrent in data:
   downloads.append( torrent )


Can you tell me the differenced on these two ways?


Aren't the result of both of them a list?

Search Discussions

  • Andreas Perstinger at Nov 2, 2013 at 1:03 pm

    On 02.11.2013 12:58, Nick the Gr33k wrote:
    Trying to add the current filename into the existent 'downloads' column
    Somehow i don't think i just use the plus sign into an existing column.
    We don't try to add numbers here but add an extra string to an already
    existing array of strings(list).

    [SNIP]

    # update specific visitor's download record
    cur.execute('''UPDATE visitors SET downloads = downloads + %s WHERE host
    = %s''', (filename, host) )
    ======================================================

    Well, when do you understand that your MySQL problems have nothing to do
    with Python?


    Everything inside the triple quotes is MySQL specific, so it's a MySQL
    problem whether you can use + to "add an extra string to an already
    existing array of strings(list)".


    This list is not a MySQL support forum.


    Bye, Andreas
  • Nick the Gr33k at Nov 2, 2013 at 4:25 pm

    ???? 2/11/2013 3:03 ??, ?/? Andreas Perstinger ??????:
    On 02.11.2013 12:58, Nick the Gr33k wrote:
    Trying to add the current filename into the existent 'downloads' column
    Somehow i don't think i just use the plus sign into an existing column.
    We don't try to add numbers here but add an extra string to an already
    existing array of strings(list). [SNIP]
    # update specific visitor's download record
    cur.execute('''UPDATE visitors SET downloads = downloads + %s WHERE host
    = %s''', (filename, host) )
    ======================================================
    Well, when do you understand that your MySQL problems have nothing to do
    with Python?

    Everything inside the triple quotes is MySQL specific, so it's a MySQL
    problem whether you can use + to "add an extra string to an already
    existing array of strings(list)".

    This list is not a MySQL support forum.

    Bye, Andreas



    [code]
       # find out if visitor had downloaded torrents in the past
       cur.execute('''SELECT torrent FROM files WHERE host = %s''', host )
       data = cur.fetchall()


       downloads = []
       if data:
        for torrent in data:
         downloads.append( torrent )
       else:
        downloads = 'None Yet'


       # add this visitor entry into database (host && downloads are unique)
       cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits, downloads) VALUES (%s, %s, %s, %s, %s, %s, %s,
    %s)''', (cID, refs, host, city, useros, browser, visits, downloads) )
    [/code]


    This works bit questios thas arises is what is its difference compare to:


    downloads.append( torrent )


    Are both these statements create a list?
    But in the latter we get the famous:
    pymysql.err.InternalError: (1241, 'Operand should contain 1 column(s)')


    while in the join() we arent getting this.


    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.


    --
    What is now proved was at first only imagined! & WebHost
    <http://superhost.gr>
  • Denis McMahon at Nov 2, 2013 at 4:43 pm

    On Sat, 02 Nov 2013 18:25:31 +0200, Nick the Gr33k wrote:


    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.

    You'd better take that up with the mysql designers.


    --
    Denis McMahon, denismfmcmahon at gmail.com
  • Rusi at Nov 2, 2013 at 5:40 pm

    On Saturday, November 2, 2013 10:13:06 PM UTC+5:30, Denis McMahon wrote:
    On Sat, 02 Nov 2013 18:25:31 +0200, Nick the Gr33k wrote:
    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.
    You'd better take that up with the mysql designers.

    That Codd...
    Should have studied some computer science


    [Ive a vague feeling I am repeating myself...]
  • Mark Lawrence at Nov 2, 2013 at 6:28 pm

    On 02/11/2013 17:40, rusi wrote:
    On Saturday, November 2, 2013 10:13:06 PM UTC+5:30, Denis McMahon wrote:
    On Sat, 02 Nov 2013 18:25:31 +0200, Nick the Gr33k wrote:

    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.
    You'd better take that up with the mysql designers.
    That Codd...
    Should have studied some computer science

    [Ive a vague feeling I am repeating myself...]

    A local lad as well, he's brought nothing but disgrace on the area.
    Apart from the fact that the vast majority of locals have never ever
    heard of him.


    --
    Python is the second best programming language in the world.
    But the best has yet to be invented. Christian Tismer


    Mark Lawrence
  • Jussi Piitulainen at Nov 2, 2013 at 6:30 pm

    rusi writes:

    On Saturday, November 2, 2013 10:13:06 PM UTC+5:30, Denis McMahon wrote:
    On Sat, 02 Nov 2013 18:25:31 +0200, Nick the Gr33k wrote:

    I just want a mysql column type that can be eligible to store an
    array of elements, a list that is, no need for having a seperate
    extra table for that if we can have a column that can store a
    list of values.
    You'd better take that up with the mysql designers.
    That Codd...
    Should have studied some computer science

    [Ive a vague feeling I am repeating myself...]

    Date and Darwen think that SQL designers should have studied and
    implemented relational theory (Codd's database theory). This doesn't
    contradict you, of course - possibly Codd should have studied CS.


    Date and Darwen think also that structured values like sets and
    relations should be allowed in a database and supported by the query
    language. Maybe their work should be taken as what Codd might think
    today, while the implementors of SQL products go their own merry ways.


    I grepped through one SQL standard on the web once to see how it
    refers to relational theory. Every single occurrence of "relation" was
    a substring of "correlational value" or something like that. My take
    from that is that SQL doesn't even pretend to be an implementation of
    Codd's theory.


    Suppose a database allowed structured values like lists of strings,
    lists of numbers, or even lists of such lists and more. Then it would
    actually be a Python issue how best to support that database.
  • Chris Angelico at Nov 2, 2013 at 9:50 pm

    On Sun, Nov 3, 2013 at 5:30 AM, Jussi Piitulainen wrote:
    Suppose a database allowed structured values like lists of strings,
    lists of numbers, or even lists of such lists and more. Then it would
    actually be a Python issue how best to support that database.

    PostgreSQL supports some higher-level structures like arrays.
    Personally, though, I think the most general representation of a
    Python list in a database is either a varchar field with some form of
    structure (eg the repr of a list), or a separate table with a foreign
    key back to this one.


    ChrisA
  • Roy Smith at Nov 2, 2013 at 10:00 pm
    In article <mailman.1959.1383429046.18130.python-list@python.org>,
      Chris Angelico wrote:

    On Sun, Nov 3, 2013 at 5:30 AM, Jussi Piitulainen
    wrote:
    Suppose a database allowed structured values like lists of strings,
    lists of numbers, or even lists of such lists and more. Then it would
    actually be a Python issue how best to support that database.
    PostgreSQL supports some higher-level structures like arrays.
    Personally, though, I think the most general representation of a
    Python list in a database is either a varchar field with some form of
    structure (eg the repr of a list), or a separate table with a foreign
    key back to this one.

    When you say "database" here, you're really talking about relational
    databases. There are other kinds.


    In MongoDB, for example, storing a list of lists of strings is a
    perfectly reasonable and straight-forward thing to do. Anything which
    can be represented by bson (which is more or less the same as anything
    which can be represented by json) can be inserted directly.
  • Chris Angelico at Nov 2, 2013 at 10:13 pm

    On Sun, Nov 3, 2013 at 9:00 AM, Roy Smith wrote:
    In article <mailman.1959.1383429046.18130.python-list@python.org>,
    Chris Angelico wrote:
    On Sun, Nov 3, 2013 at 5:30 AM, Jussi Piitulainen
    wrote:
    Suppose a database allowed structured values like lists of strings,
    lists of numbers, or even lists of such lists and more. Then it would
    actually be a Python issue how best to support that database.
    PostgreSQL supports some higher-level structures like arrays.
    Personally, though, I think the most general representation of a
    Python list in a database is either a varchar field with some form of
    structure (eg the repr of a list), or a separate table with a foreign
    key back to this one.
    When you say "database" here, you're really talking about relational
    databases. There are other kinds.

    Quite right, my apologies. I'm talking about the classic relational
    database accessed by SQL, which is what the OP's currently working
    with (MySQL). I've worked with other types of database, but was trying
    to stick as closely as possible to the question. But yes, the
    clarification is important here.


    ChrisA
  • Walter Hurry at Nov 2, 2013 at 9:12 pm

    On Sat, 02 Nov 2013 10:40:58 -0700, rusi wrote:


    That Codd...
    Should have studied some computer science

    [Ive a vague feeling I am repeating myself...]

    ROFL. Get thee into FNF!
  • Gregory Ewing at Nov 3, 2013 at 6:06 am

    Nick the Gr33k wrote:
    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.

    Relational database systems typically don't provide any
    such type, because it's not the recommended way of storing
    that kind of data in a relational database.


    The recommended way is to use a secondary table, as has
    been pointed out.


    You're making things difficult for yourself by refusing
    to consider that solution.


    --
    Greg
  • Antoon Pardon at Nov 3, 2013 at 9:56 am

    Op 03-11-13 07:06, Gregory Ewing schreef:
    Nick the Gr33k wrote:
    I just want a mysql column type that can be eligible to store an array of elements, a list that is, no need for having a seperate extra table for that if we can have a column that can store a list of values.
    Relational database systems typically don't provide any
    such type, because it's not the recommended way of storing
    that kind of data in a relational database.

    The recommended way is to use a secondary table, as has
    been pointed out.

    You're making things difficult for yourself by refusing
    to consider that solution.
    You are talking to Nikos! The person who choose code because
    he prefers how it looks over examples of working code.


    --
    Antoon Pardon
  • Roy Smith at Nov 3, 2013 at 12:16 pm
    In article <bdm7fif28rru1@mid.individual.net>,
      Gregory Ewing wrote:

    Nick the Gr33k wrote:
    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.
    Relational database systems typically don't provide any
    such type, because it's not the recommended way of storing
    that kind of data in a relational database.

    The recommended way is to use a secondary table, as has
    been pointed out.

    Most SQL databases allow you to store arbitrary data as an opaque value
    (i.e. BLOB). So, one possibility would be to just serialize your list
    (pickle, json, whatever) and store it that way. I've seen databases
    that didn't use BLOB, but just stored json in a string field.


    The limitation, of course, is that the data is opaque as far as the
    database goes; you can't do queries against it. But, if all you need to
    do is store the list and be able to retrieve it, it's a perfectly
    reasonable thing to do, and a lot more efficient than doing a join on a
    secondary table.


    Normalization is for database weenies :-)
  • Chris Angelico at Nov 3, 2013 at 1:13 pm

    On Sun, Nov 3, 2013 at 11:16 PM, Roy Smith wrote:
    The limitation, of course, is that the data is opaque as far as the
    database goes; you can't do queries against it. But, if all you need to
    do is store the list and be able to retrieve it, it's a perfectly
    reasonable thing to do, and a lot more efficient than doing a join on a
    secondary table.

    Yeah, that can be an effective way to store complex data - especially
    if the nesting level isn't fixed. (Normalization can handle a
    single-level list, but it's a lot messier for handling lists of lists,
    for instance.)


    I still think that the OP's task would be best suited to a separate
    table (one table of visitors, another of downloads, where the
    Downloads table has a foreign key to Visitors), but I'm reminded of
    XKCD 1027: the thing standing in the way of his code is that the
    person coding it... is him. And of course, this is all without getting
    into the non-code aspects of this proposal - as have been mentioned
    several times, like EU regulations on retaining this level of data.


    ChrisA
  • Nick the Gr33k at Nov 4, 2013 at 5:03 pm

    ???? 3/11/2013 2:16 ??, ?/? Roy Smith ??????:
    In article <bdm7fif28rru1@mid.individual.net>,
    Gregory Ewing wrote:
    Nick the Gr33k wrote:
    I just want a mysql column type that can be eligible to store an array
    of elements, a list that is, no need for having a seperate extra table
    for that if we can have a column that can store a list of values.
    Relational database systems typically don't provide any
    such type, because it's not the recommended way of storing
    that kind of data in a relational database.

    The recommended way is to use a secondary table, as has
    been pointed out.
    Most SQL databases allow you to store arbitrary data as an opaque value
    (i.e. BLOB). So, one possibility would be to just serialize your list
    (pickle, json, whatever) and store it that way. I've seen databases
    that didn't use BLOB, but just stored json in a string field.

    The limitation, of course, is that the data is opaque as far as the
    database goes; you can't do queries against it. But, if all you need to
    do is store the list and be able to retrieve it, it's a perfectly
    reasonable thing to do, and a lot more efficient than doing a join on a
    secondary table.

    Normalization is for database weenies :-)

    Exactly my sentiments Roy!


    Call me picky but even if they try to hit me hard i wll always get to
    pick the simplest and better looking way.




    I have managed to make my code work by:




    create table visitors
    (
        counterID integer(5) not null,
        host varchar(50) not null,
        refs varchar(25) not null,
        city varchar(20) not null,
        userOS varchar(10) not null,
        browser varchar(10) not null,
        visits datetime not null,
        hits integer(5) not null default 1,
        downloads varchar(50) not null default '',
        foreign key (counterID) references counters(ID),
        unique index (visits)
       )ENGINE = MYISAM;




    =============================================
    # add this visitor entry into database (hits && downloads are defaulted)
    cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits) VALUES (%s, %s, %s, %s, %s, %s, %s)''', (cID,
    ref, host, city, useros, browser, lastvisit) )
    =============================================


    and later on ....


    =============================================
    torrents = []
    # check if visitor has downloaded movies
    for download in downloads:
      if download != '':
       torrents.append( download )


    # present visitor's movie picks if any
    if torrents:
      print( '<td><select>' )
       for n, torrent in enumerate( torrents ):
       if n == 0:
        op_selected = 'selected'
       else:
        op_selected = ''
       print( '<option %s> %s </option>' % (op_selected, torrent) )
      print( '</select></td>' )
    else:
      print( '<td><center><b><font color=white> ??? ????????????????? ?????!
    </td>' )
    break
    =============================================




    Please since this column you mentioned is able to store a Python's list
    datatype could you tell me what needs alternation in:


    1. MySQL's visitor's table definition time
    2. python database cur.execute method
    3. retrieval time


    Thank you very much for anyone wishes to give me a hand here.
  • Denis McMahon at Nov 4, 2013 at 10:46 pm

    On Mon, 04 Nov 2013 19:03:58 +0200, Nick the Gr33k wrote:


    Please since this column you mentioned is able to store a Python's list
    datatype could you tell me what needs alternation in:

    We've already told you, there is NO mysql datatype that can store a
    python list directly. There are ways of storing lists in mysql, but you
    can't pass a list directly into a mysql update or insert query as a
    single record field (you may be able to pass a list of tuples in for a
    multi row update or insert, but that's a different issue).


    You could convert the python list into a storable entity, for example
    imploding a list of strings with some arbitrary separator to create a
    long string, store the long string, then when you read it from the
    database explode it back into a list.


    Or you could store each element of the list in a "downloads" tables along
    with a reference to the associated record in the "users" table.


    These are two possible methods of storing a list that is associated with
    a user entry. Which method you use is up to you. There may be others.
    Pick a method and code it.


    There is no built in support in the python / mysql system for putting a
    list straight into a database, because mysql does not have a "collection"
    record type.


    --
    Denis McMahon, denismfmcmahon at gmail.com
  • Nick the Gr33k at Nov 5, 2013 at 6:54 am

    ???? 5/11/2013 12:46 ??, ?/? Denis McMahon ??????:
    On Mon, 04 Nov 2013 19:03:58 +0200, Nick the Gr33k wrote:
    There is no built in support in the python / mysql system for puttinga
    list straight into a database, because mysql does not have"collection"
    record type.

    Does postgresql has this 'collection' record type



    You could convert the python list into a storable entity, for example
    imploding a list of strings with some arbitrary separator to create a
    long string, store the long string, then when you read it from the
    database explode it back into a list.
    Which method you use is up to you. There may be others.
    Pick a method and code it.

    Okey here is my attempt to code your solution as best as i can get my
    head around it:


    This is the part that is responsible to do the database insertion
    converting scalars to lists and backwards.


    =====================================
      try:
       # if first time for webpage; create new record( primary key is
    automatic, hit is defaulted ), if page exists then update record
       cur.execute('''INSERT INTO counters (url) VALUES (%s) ON DUPLICATE KEY
    UPDATE hits = hits + 1''', page )
       cID = cur.lastrowid


       # fetch those columns that act as lists but are stored as strings
       cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = %s''', cID )
       data = cur.fetchone


       ref = data[0]
       visit = data[1]
       download = data[2]


       # retrieve long strings and convert them into lists respectively
       refs = ref.split()
       visits = visit.split()
       downloads = download.split()


       # add current strings to the each list respectively
       refs.appends( ref )
       visits.appends( visit )
       downloads.appends( download )


       # convert lists back to longstrings
       refs = ', '.join( refs )
       visits = ', '.join( visits )
       downloads = ', '.join( downloads )


       # add this visitor entry into database (hits && downloads are defaulted)
       cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits, hits = hits + 1, downloads) VALUES (%s, %s, %s,
    %s, %s, %s, %s, %s, %s)''',
           (cID, refs, host, city, useros, browser, visits, hits, downloads) )


       con.commit()
      except pymysql.ProgrammingError as e:
       print( repr(e) )
       con.rollback()
       sys.exit(0)
    ===================================


    Please tell me if this logic is correct, for some reason it doesn't do
    what i need it to do.


    Thank you.
  • Nick the Gr33k at Nov 5, 2013 at 8:07 am

    ???? 5/11/2013 8:54 ??, ?/? Nick the Gr33k ??????:
    ???? 5/11/2013 12:46 ??, ?/? Denis McMahon ??????:
    On Mon, 04 Nov 2013 19:03:58 +0200, Nick the Gr33k wrote:
    There is no built in support in the python / mysql system for puttinga
    list straight into a database, because mysql does not have"collection"
    record type.
    Does postgresql has this 'collection' record type

    You could convert the python list into a storable entity, for example
    imploding a list of strings with some arbitrary separator to create a
    long string, store the long string, then when you read it from the
    database explode it back into a list.
    Which method you use is up to you. There may be others.
    Pick a method and code it.
    Okey here is my attempt to code your solution as best as i can get my
    head around it:

    This is the part that is responsible to do the database insertion
    converting scalars to lists and backwards.

    =====================================
    try:
    # if first time for webpage; create new record( primary key is
    automatic, hit is defaulted ), if page exists then update record
    cur.execute('''INSERT INTO counters (url) VALUES (%s) ON
    DUPLICATE KEY UPDATE hits = hits + 1''', page )
    cID = cur.lastrowid

    # fetch those columns that act as lists but are stored as strings
    cur.execute('''SELECT refs, visits, downloads FROM visitors
    WHERE counterID = %s''', cID )
    data = cur.fetchone

    ref = data[0]
    visit = data[1]
    download = data[2]

    # retrieve long strings and convert them into lists respectively
    refs = ref.split()
    visits = visit.split()
    downloads = download.split()

    # add current strings to the each list respectively
    refs.appends( ref )
    visits.appends( visit )
    downloads.appends( download )

    # convert lists back to longstrings
    refs = ', '.join( refs )
    visits = ', '.join( visits )
    downloads = ', '.join( downloads )

    # add this visitor entry into database (hits && downloads are
    defaulted)
    cur.execute('''INSERT INTO visitors (counterID, refs, host,
    city, useros, browser, visits, hits = hits + 1, downloads) VALUES (%s,
    %s, %s, %s, %s, %s, %s, %s, %s)''',
    (cID, refs, host, city, useros, browser,
    visits, hits, downloads) )

    con.commit()
    except pymysql.ProgrammingError as e:
    print( repr(e) )
    con.rollback()
    sys.exit(0)
    ===================================

    Please tell me if this logic is correct, for some reason it doesn't do
    what i need it to do.

    Thank you.



    Better version for it, i think, but still none working:


    =========================================
       # if first time for webpage; create new record( primary key is
    automatic, hit is defaulted ), if page exists then update record
       cur.execute('''INSERT INTO counters (url) VALUES (%s) ON DUPLICATE KEY
    UPDATE hits = hits + 1''', page )
       cID = cur.lastrowid


       # fetch those columns that act as lists but are stored as strings
       cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = (SELECT ID FROM counters WHERE url = %s) ORDER BY visits
    DESC''', page )
       data = cur.fetchall


       for row in data:
        (refs, visits, downloads) = row


        # retrieve long strings and convert them into lists respectively
        refs = ref.split()
        visits = visit.split()
        downloads = download.split()


        # add current strings to each list respectively
        refs.appends( ref )
        visits.appends( visit )
        downloads.appends( download )


        # convert lists back to longstrings
        refs = ', '.join( refs )
        visits = ', '.join( visits )
        downloads = ', '.join( downloads )


        # add this visitor entry into database (hits && downloads are defaulted)
        cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits, hits = hits + 1, downloads) VALUES (%s, %s, %s,
    %s, %s, %s, %s, %s, %s)''',
            (cID, refs, host, city, useros, browser, visits, hits, downloads) )
    =========================================


    [Tue Nov 05 10:06:57 2013] [error] [client 176.92.96.218] Traceback
    (most recent call last):
    [Tue Nov 05 10:06:57 2013] [error] [client 176.92.96.218] File
    "/home/nikos/public_html/cgi-bin/metrites.py", line 267, in <module>
    [Tue Nov 05 10:06:57 2013] [error] [client 176.92.96.218] for row in
    data:
    [Tue Nov 05 10:06:57 2013] [error] [client 176.92.96.218] TypeError:
    'method' object is not iterable


    How is ti possible for data to be none iterable?
  • Chris Angelico at Nov 5, 2013 at 8:21 am

    On Tue, Nov 5, 2013 at 7:07 PM, Nick the Gr33k wrote:
    How is ti possible for data to be none iterable?

    Do you know how to call a method in Python? If not, go back to the
    beginning of the tutorial and start reading. If so, look through your
    code and see where you have a 'method' object that you are trying to
    treat as iterable. It's really REALLY obvious, and you even have the
    line number to tell you.


    Nick, you *need* to learn how to read Python tracebacks. They are
    incredibly helpful. Be glad you don't just get "Segmentation fault"
    and a process termination (or, worse, a security hole).


    ChrisA
  • Antoon Pardon at Nov 5, 2013 at 8:39 am

    Op 05-11-13 09:21, Chris Angelico schreef:
    On Tue, Nov 5, 2013 at 7:07 PM, Nick the Gr33k wrote:
    How is ti possible for data to be none iterable?
    Do you know how to call a method in Python? If not, go back to the
    beginning of the tutorial and start reading. If so, look through your
    code and see where you have a 'method' object that you are trying to
    treat as iterable. It's really REALLY obvious, and you even have the
    line number to tell you.

    Nick, you *need* to learn how to read Python tracebacks. They are
    incredibly helpful. Be glad you don't just get "Segmentation fault"
    and a process termination (or, worse, a security hole).

    No he doesn't. It seems there will always be someone who can't resist
    the temptation to spoon feed him. Sooner or later someone will provide
    him the answer he craves.


    So no, Nikos doesn't need to learn anything.


    --
    Antoon Pardon
  • Nick the Gr33k at Nov 5, 2013 at 8:53 am

    ???? 5/11/2013 10:21 ??, ?/? Chris Angelico ??????:
    On Tue, Nov 5, 2013 at 7:07 PM, Nick the Gr33k wrote:
    How is ti possible for data to be none iterable?
    Do you know how to call a method in Python? If not, go back to the
    beginning of the tutorial and start reading. If so, look through your
    code and see where you have a 'method' object that you are trying to
    treat as iterable. It's really REALLY obvious, and you even have the
    line number to tell you.

    Nick, you *need* to learn how to read Python tracebacks. They are
    incredibly helpful. Be glad you don't just get "Segmentation fault"
    and a process termination (or, worse, a security hole).





    data = cur.fetchall


    for row in data:


    the only thing i can understand by looking the above 2 lines is this:


    'fo'r fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated.


    But that just doesn't hlp me much.
  • Nick the Gr33k at Nov 5, 2013 at 8:54 am

    ???? 5/11/2013 10:21 ??, ?/? Chris Angelico ??????:
    On Tue, Nov 5, 2013 at 7:07 PM, Nick the Gr33k wrote:
    How is ti possible for data to be none iterable?
    Do you know how to call a method in Python? If not, go back to the
    beginning of the tutorial and start reading. If so, look through your
    code and see where you have a 'method' object that you are trying to
    treat as iterable. It's really REALLY obvious, and you even have the
    line number to tell you.

    Nick, you *need* to learn how to read Python tracebacks. They are
    incredibly helpful. Be glad you don't just get "Segmentation fault"
    and a process termination (or, worse, a security hole).



    ===============
    data = cur.fetchall
    for row in data:
    ===============


    The only thing i can understand by looking the above 2 lines is this:


    'for' fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated row by row.


    But that just doesn't help me much.
  • M.F. at Nov 5, 2013 at 9:10 am

    On 11/05/2013 04:54 PM, Nick the Gr33k wrote:

    ===============
    data = cur.fetchall
    data = cur.fetchall()
    That is what the stack trace and Christ tried to inform you.
    for row in data:
    ===============

    The only thing i can understand by looking the above 2 lines is this:

    'for' fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated row by row.

    But that just doesn't help me much.
  • Nick the Gr33k at Nov 5, 2013 at 9:34 am

    ???? 5/11/2013 11:10 ??, ?/? M.F. ??????:
    On 11/05/2013 04:54 PM, Nick the Gr33k wrote:


    ===============
    data = cur.fetchall
    data = cur.fetchall()
    That is what the stack trace and Christ tried to inform you.
    for row in data:
    ===============

    The only thing i can understand by looking the above 2 lines is this:

    'for' fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated row by row.

    But that just doesn't help me much.

    I see, but because of the traceback not being to express it more easily
    i was under the impression that data wasn't what i expected it to be.
  • Nick the Gr33k at Nov 5, 2013 at 9:56 am

    ???? 5/11/2013 11:34 ??, ?/? Nick the Gr33k ??????:
    ???? 5/11/2013 11:10 ??, ?/? M.F. ??????:
    On 11/05/2013 04:54 PM, Nick the Gr33k wrote:


    ===============
    data = cur.fetchall
    data = cur.fetchall()
    That is what the stack trace and Christ tried to inform you.
    for row in data:
    ===============

    The only thing i can understand by looking the above 2 lines is this:

    'for' fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated row by row.

    But that just doesn't help me much.
    I see, but because of the traceback not being to express it more easily
    i was under the impression that data wasn't what i expected it to be.



    Still similar error here:


    =================================
       # if first time for webpage; create new record( primary key is
    automatic, hit is defaulted ), if page exists then update record
       cur.execute('''INSERT INTO counters (url) VALUES (%s) ON DUPLICATE KEY
    UPDATE hits = hits + 1''', page )
       cID = cur.lastrowid


       # fetch those columns that act as lists but are stored as strings
       cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = %s and host = %s''', (cID, host) )
       data = cur.fetchone()


       # unpack data into variables
       (ref, visit, download) = data


       # retrieve long strings and convert them into lists respectively
       refs = ref.split()
       visits = visit.split()
       downloads = download.split()


       # add current strings to each list respectively
       refs.append( ref )
       visits.append( visit )
       downloads.append( download )


       # convert lists back to longstrings
       refs = ', '.join( refs )
       visits = ', '.join( visits )
       downloads = ', '.join( downloads )


       # save this visit as an entry into database
       cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits, hits = hits + 1, downloads) VALUES (%s, %s, %s,
    %s, %s, %s, %s, %s, %s)''',
           (cID, refs, host, city, useros, browser, visits, hits, downloads) )
    ================================




    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] File
    "/home/nikos/public_html/cgi-bin/metrites.py", line 268, in <module>
    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] (ref,
    visit, download) = data
    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] TypeError:
    'NoneType' object is not iterable




    Now i have the parenthesis around fetchone().
    How the data cant be properly unpacked?
  • Antoon Pardon at Nov 5, 2013 at 10:20 am

    Op 05-11-13 10:56, Nick the Gr33k schreef:
    ???? 5/11/2013 11:34 ??, ?/? Nick the Gr33k ??????:
    ???? 5/11/2013 11:10 ??, ?/? M.F. ??????:
    On 11/05/2013 04:54 PM, Nick the Gr33k wrote:


    ===============
    data = cur.fetchall
    data = cur.fetchall()
    That is what the stack trace and Christ tried to inform you.
    for row in data:
    ===============

    The only thing i can understand by looking the above 2 lines is this:

    'for' fails to iterate over 'data' because for some reason 'data'
    haven't resulted as a list of rows that can be iterated row by row.

    But that just doesn't help me much.
    I see, but because of the traceback not being to express it more easily
    i was under the impression that data wasn't what i expected it to be.

    Still similar error here:

    =================================
    # if first time for webpage; create new record( primary key is
    automatic, hit is defaulted ), if page exists then update record
    cur.execute('''INSERT INTO counters (url) VALUES (%s) ON
    DUPLICATE KEY UPDATE hits = hits + 1''', page )
    cID = cur.lastrowid

    # fetch those columns that act as lists but are stored as strings
    cur.execute('''SELECT refs, visits, downloads FROM visitors
    WHERE counterID = %s and host = %s''', (cID, host) )
    data = cur.fetchone()

    # unpack data into variables
    (ref, visit, download) = data

    # retrieve long strings and convert them into lists respectively
    refs = ref.split()
    visits = visit.split()
    downloads = download.split()

    # add current strings to each list respectively
    refs.append( ref )
    visits.append( visit )
    downloads.append( download )

    # convert lists back to longstrings
    refs = ', '.join( refs )
    visits = ', '.join( visits )
    downloads = ', '.join( downloads )

    # save this visit as an entry into database
    cur.execute('''INSERT INTO visitors (counterID, refs, host,
    city, useros, browser, visits, hits = hits + 1, downloads) VALUES (%s,
    %s, %s, %s, %s, %s, %s, %s, %s)''',
    (cID, refs, host, city, useros, browser, visits,
    hits, downloads) )
    ================================


    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] File
    "/home/nikos/public_html/cgi-bin/metrites.py", line 268, in <module>
    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] (ref,
    visit, download) = data
    [Tue Nov 05 11:55:21 2013] [error] [client 176.92.96.218] TypeError:
    'NoneType' object is not iterable


    Now i have the parenthesis around fetchone().
    How the data cant be properly unpacked?
    Did you read the documentation of fetchone?


    --
    Antoon Pardon
  • Nick the Gr33k at Nov 5, 2013 at 10:33 am

    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:


    Did you read the documentation of fetchone?





    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.


    I dont know why it copmains about:
    TypeError: 'NoneType' object is not iterable


    what object is supposed to have benn of None type?
    how do i check for it?
  • Antoon Pardon at Nov 5, 2013 at 10:59 am

    Op 05-11-13 11:33, Nick the Gr33k schreef:
    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:
    Did you read the documentation of fetchone?


    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.
    From this answer it seems you didn't read the documentation very carefully.
    I dont know why it copmains about:
    TypeError: 'NoneType' object is not iterable

    what object is supposed to have benn of None type?
    how do i check for it?

    This is realy rather basic python knowledge. But maybe things
    become clear after you read the documentation of fetchone more
    carefully.


    --
    Antoon Pardon
  • Dave Angel at Nov 5, 2013 at 11:16 am

    On Tue, 05 Nov 2013 12:33:49 +0200, Nick the Gr33k wrote:
    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:
    Did you read the documentation of fetchone?






    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.

    That's not the only difference. See the word None there in one of the
    descriptions?

    TypeError: 'NoneType' object is not iterable

    Examine the statement it's complaining about. It's obvious which item
    it's trying to iterate over.


    --
    DaveA
  • Steven D'Aprano at Nov 5, 2013 at 11:49 am

    On Tue, 05 Nov 2013 12:33:49 +0200, Nick the Gr33k wrote:


    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:
    Did you read the documentation of fetchone?


    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.

    Read the documentation of fetchone again:


    http://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.fetchone


    Take careful note of what it does when there is no more data to fetch.





    I dont know why it copmains about:
    TypeError: 'NoneType' object is not iterable

    what object is supposed to have benn of None type? how do i check for
    it?

    Does the name "NoneType" give you a hint? Repeat after me:


    "The type of **** is NoneType."


    Take a guess what the **** should be. Then test it, in the interactive
    interpreter:


    type(****) # replace the stars with the object




    and see what is printed.






    --
    Steven
  • Nick the Gr33k at Nov 5, 2013 at 12:25 pm

    ???? 5/11/2013 1:49 ??, ?/? Steven D'Aprano ??????:
    On Tue, 05 Nov 2013 12:33:49 +0200, Nick the Gr33k wrote:

    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:
    Did you read the documentation of fetchone?


    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.
    Read the documentation of fetchone again:

    http://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.fetchone

    Take careful note of what it does when there is no more data to fetch.


    I dont know why it copmains about:
    TypeError: 'NoneType' object is not iterable

    what object is supposed to have benn of None type? how do i check for
    it?
    Does the name "NoneType" give you a hint? Repeat after me:

    "The type of **** is NoneType."

    Take a guess what the **** should be. Then test it, in the interactive
    interpreter:

    type(****) # replace the stars with the object


    and see what is printed.




    # fetch those columns that act as lists but are stored as strings
    cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = %s and host = %s''', (cID, host) )
    data = cur.fetchone()


    print( type(data) )
    sys.exit(0)


    i tried inserting a type function to notify me of the datatype of 'data'
    but that didnt help too.


    Still:
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] File
    "/home/nikos/public_html/cgi-bin/metrites.py", line 268, in <module>
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] (ref,
    visit, download) = data
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] TypeError:
    'NoneType' object is not iterable


    Unfortunately i still miss your point.
  • Antoon Pardon at Nov 5, 2013 at 12:42 pm
    Op 05-11-13 13:25, Nick the Gr33k schreef:
    # fetch those columns that act as lists but are stored as strings
    cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = %s and host = %s''', (cID, host) )
    data = cur.fetchone()

    print( type(data) )
    sys.exit(0)

    i tried inserting a type function to notify me of the datatype of 'data'
    but that didnt help too.

    Still:
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] File
    "/home/nikos/public_html/cgi-bin/metrites.py", line 268, in <module>
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] (ref,
    visit, download) = data
    [Tue Nov 05 14:22:32 2013] [error] [client 176.92.96.218] TypeError:
    'NoneType' object is not iterable

    Unfortunately i still miss your point.

    *Read* the documentation of fetchone! The information you need is there.


    --
    Antoon Pardon
  • Dave Angel at Nov 5, 2013 at 1:15 pm

    On Tue, 05 Nov 2013 14:25:41 +0200, Nick the Gr33k wrote:
    i tried inserting a type function to notify me of the datatype of 'data'
    but that didnt help too.

    What did that print show ? In what way didn't it help?


    It said the type was Charles
    It didn'tprint anything
    It gave some other error
    It formattedmy drive


    How far did you get on the exercise I suggested?


    --
    DaveA
  • Joel Goldstick at Nov 5, 2013 at 3:44 pm
    As I read this thread, the original question was how to stuff
    multiple values in a single sql column. Several people pointed out
    that the proper way to handle multiple values related to the original
    table is to use a second table or perhaps a many to many relationship
    with and intermediate join table. Some people, including the original
    poster seem to want to shoe horn the data into a single field. --
    blobs, strings, even python lists, etc. Although there is nothing
    stopping a coder from doing that (except lack of skill ;)), it is a
    bad idea. SQL, whether a complete implementation of Codd stuff, or a
    reasonable facsimile is a system that makes it possible to make
    complex queries on data stored properly. If you break the normal
    forms, you always end up not being able to use sql statements to get
    everything out that you put in.


    So, some people here seem to think that's ok. It may get the poster
    past his first step more quickly than taking the time to understand
    the tools he is using. But eventually, there will be a big cost to
    extending the code. And we will endure another thread like this.
    Personally, I think it demeans the group.


    Once again we get the pattern:


    How do I do this?


    1. Here's how


    No, I don't like that way


    2. Here's a bad way


    Oh good, will you write it for me.














    --
    Joel Goldstick
    http://joelgoldstick.com
  • Nick the Gr33k at Nov 5, 2013 at 3:39 pm

    ???? 5/11/2013 3:15 ??, ?/? Dave Angel ??????:
    On Tue, 05 Nov 2013 14:25:41 +0200, Nick the Gr33k
    wrote:
    i tried inserting a type function to notify me of the datatype of 'data'
    but that didnt help too.
    What did that print show ? In what way didn't it help?

    It said the type was Charles
    It didn'tprint anything
    It gave some other error
    It formattedmy drive

    How far did you get on the exercise I suggested?





    nikos at superhost.gr [~]# who
    nikos pts/0 Nov 5 09:57 (176.92.96.218)
    nikos at superhost.gr [~]# who > myfile.txt
    nikos at superhost.gr [~]# cat myfile.txt
    nikos pts/0 Nov 5 09:57 (176.92.96.218)
    nikos at superhost.gr [~]# python
    Python 3.3.2 (default, Aug 26 2013, 06:41:42)
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    infile = open("myfile.txt")
    data = infile.readlines
    for line in data:
    ... print( line )
        File "<stdin>", line 2
          print( line )
              ^
    IndentationError: expected an indented block
    for line in data:
    ... print( line )
    ...
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    TypeError: 'builtin_function_or_method' object is not iterable


    You said that i should try it locally but on my 8.1 i do not have python
    installed i test and run everything on server.


    So, i tried it at the interpreter and it gave me the same error.
  • Tim Chase at Nov 5, 2013 at 3:45 pm

    On 2013-11-05 17:39, Nick the Gr33k wrote:
    data = infile.readlines

    You're assigning it to the bound function rather than calling the
    function. Use the "call" operator:


       data = infile.readlines()


    -tkc
  • Dave Angel at Nov 6, 2013 at 5:36 am

    On Tue, 5 Nov 2013 09:45:15 -0600, Tim Chase wrote:
    You're assigning it to the bound function rather than calling the
    function. Use the "call" operator:
    data = infile.readlines()

    Thanks for spoiling the lesson. Nicks needs to learn how to debug 4
    line programs without someone giving him the answer.


    --
    DaveA
  • Mark Lawrence at Nov 6, 2013 at 8:53 am

    On 06/11/2013 05:36, Dave Angel wrote:
    On Tue, 5 Nov 2013 09:45:15 -0600, Tim Chase
    wrote:
    You're assigning it to the bound function rather than calling the
    function. Use the "call" operator:
    data = infile.readlines()
    Thanks for spoiling the lesson. Nicks needs to learn how to debug 4 line
    programs without someone giving him the answer.

    He needs to learn on short, consise programs before moving up to the
    medium size 4 liners.


    --
    Python is the second best programming language in the world.
    But the best has yet to be invented. Christian Tismer


    Mark Lawrence
  • Nick the Gr33k at Nov 5, 2013 at 3:50 pm

    ???? 5/11/2013 5:45 ??, ?/? Tim Chase ??????:
    On 2013-11-05 17:39, Nick the Gr33k wrote:
    data = infile.readlines
    You're assigning it to the bound function rather than calling the
    function. Use the "call" operator:

    data = infile.readlines()

    -tkc



    --
    infile=open("myfile.txt")
    data = infile.readlines()
    for line in data:
    ... print( line )
    ...
    nikos pts/0 Nov 5 09:57 (176.92.96.218)


    >>>


    Thanks Tim.
    So i see here 2 lines, first being the file contenat's themselves and
    the last one being an empty line.


    I can't relate this to the NoneType error iam having in my script.
  • Nick the Gr33k at Nov 5, 2013 at 4:20 pm

    ???? 5/11/2013 1:16 ??, ?/? Dave Angel ??????:
    On Tue, 05 Nov 2013 12:33:49 +0200, Nick the Gr33k
    wrote:
    ???? 5/11/2013 12:20 ??, ?/? Antoon Pardon ??????:
    Did you read the documentation of fetchone?


    fetchone is like fetchall except from the fact that the former returned
    a row of data while the latter returned a list of rows of data.
    That's not the only difference. See the word None there in one of the
    descriptions?
    TypeError: 'NoneType' object is not iterable
    Examine the statement it's complaining about. It's obvious which item
    it's trying to iterate over.



    --


    So perhaps 'data' coudlnt retrive any values from the database that why
    it cannot unpack them to the 3 variables?


    if so i altered the code to:


       # fetch those columns that act as lists but are stored as strings
       cur.execute('''SELECT refs, visits, downloads FROM visitors WHERE
    counterID = %s and host = %s''', (cID, host) )
       data = cur.fetchone()


       ref = visit = download = []
       if cur.rowcount:
        # unpack data into variables
        (ref, visit, download) = data


        # retrieve long strings and convert them into lists respectively
        refs = ref.split()
        visits = visit.split()
        downloads = download.split()
       else:
        # initiate these values
        ref = ref
        visit = lastvisit
        download = ''


       # add current strings to each list respectively
       refs.append( ref )
       visits.append( visit )
       downloads.append( download )


       # convert lists back to longstrings
       refs = ', '.join( refs )
       visits = ', '.join( visits )
       downloads = ', '.join( downloads )


       # save this visit as an entry into database
       cur.execute('''INSERT INTO visitors (counterID, refs, host, city,
    useros, browser, visits, hits = hits + 1, downloads) VALUES (%s, %s, %s,
    %s, %s, %s, %s, %s, %s)''',
           (cID, refs, host, city, useros, browser, visits, hits, downloads) )
    =======================


    but this also fail to run :( :( :(
  • Dave Angel at Nov 5, 2013 at 11:00 am

    On Tue, 05 Nov 2013 11:34:53 +0200, Nick the Gr33k wrote:
    I see, but because of the traceback not being to express it more easily
    i was under the impression that data wasn't what i expected it to
    be.


    Exactly. So why didn't you act on that impression?


    Your error message told you that data was a method, and that a method
    is not iterable. The previous line is where you assigned it.


    Try debugging this:


    infile = open("myfile.txt")
    data = infile.readlines
      for line in data:
         print(line)


    Not on a server. On your own machine.


    --
    DaveA
  • Denis McMahon at Nov 5, 2013 at 5:48 pm

    On Tue, 05 Nov 2013 11:34:53 +0200, Nick the Gr33k wrote:


    data = cur.fetchall
    for row in data:
    I see, but because of the traceback not being to express it more easily
    i was under the impression that data wasn't what i expected it to be.

    data wasn't what you expected it to be.


    The problem was that you didn't understand that the reason data wasn't
    what you expected it to be was that you had assigned data to be the
    fetchall method of the object cur, when what you wanted to do was assign
    data to be the results of executing the method fetchall on the object cur.


    Both of these are legal assignments:


    data = cur.fetchall
    data = cur.fetchall()


    However the following is only valid if data is iterable:


    for row in data:


    So when it reaches the the line:


    for row in data:


    and discovers that data is not an iterable type, it gives an error
    message. If you can't decipher the error message to get back to the fact
    that in this case data isn't a y that you can use "for x in y:" to
    iterate over, and then debug intelligently to determine how any why that
    error message occurred, then as has been suggested many times in the
    past, you should stop trying to write code.


    Seriously, how many other people do you see repeatedly posting "I don't
    understand the error, help" messages here that have been caused by such
    simple coding mistakes?


    Most of us can decipher these error messages ourselves and would be
    embarrassed to post asking for help.


    --
    Denis McMahon, denismfmcmahon at gmail.com
  • Chris Angelico at Nov 5, 2013 at 10:01 am

    On Tue, Nov 5, 2013 at 8:10 PM, M.F. wrote:
    That is what the stack trace and Christ tried to inform you.

    Let's go with "and Chris tried"... no need to promote me to deity status :)


    ChrisA
  • Antoon Pardon at Nov 5, 2013 at 10:07 am

    Op 05-11-13 10:10, M.F. schreef:
    On 11/05/2013 04:54 PM, Nick the Gr33k wrote:


    ===============
    data = cur.fetchall
    data = cur.fetchall()
    That is what the stack trace and Christ tried to inform you.

    And now you have depraved Nikos of the opportunity to really learn
    something. I'm willing to bet that Nikos will encouter a similar
    problem within a year. And because he didn't need to learn how
    to find the bug now, he will have no idea how to track the bug
    then and will come here again with the expectation that someone
    here will just spoon feed him the answer he needs.


    And so continues the endless Nikos cycle.


    --
    Antoon Pardon
  • Larry Hudson at Nov 6, 2013 at 4:52 am

    On 11/05/2013 02:07 AM, Antoon Pardon wrote:
    And now you have depraved Nikos of the opportunity to really learn
    something. ...

    I know you meant "deprived", but "depraved Nikos" sounds like a good description to me. ;-)


           -=- Larry -=-

Related Discussions

People

Translate

site design / logo © 2022 Grokbase