Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Try this instead:

         # force all issues other than "Operations" to "Other"
         if tipo != "Operations":
             tipo = "Other"
razstec commented: it worked like my example, i seems to work fine but the data it sends is incomplete, maybe there was a problem migrating to the cloud server :( +3
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

You've checked the boot order in the BIOS, correct?
Speaking of which, since you mentioned that this is an older system: is it UEFI, or Legacy BIOS?
Also, how did you install Ubuntu originally (assuming it was installed already and that the error message is from the HDD boot)?
Did the error message include any other details beyond the message you already posted?

EDIT: Doing a quick search on the error message, it looks to be a Gnome error rather than a Linux one (which I was wondering about, it was far too casual a message for the Linux kernel). If so, it should be possible to use Ctl-Alt-F2 to get to a shell. You should be able to remove and reinstall Gnome itself in that case.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Sorry for the delay in getting back to you, I'll see what I can find out.

razstec commented: no worrys, this seems a easy one but oddly i can only open in new window and really need it in a frame or something to add to the layout of my project +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Just what do you mean by 'changeable'? Does it have to be able to view different websites, rather than the hardcoded one? Or something else?

Also, are you sure you want to be mixing TkInter and Qt like that? I'm not certain that that would really work consistently. If you need the Qt browser tool, I would use Qt for the whole UI.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

You would add it to the add_axes() call, like so:

    axes = fig.add_axes([0.1, 0.1, 0.8, 0.8],
                        xticks=range(len(labels)),
                        xticklabels=labels,
                        xlabel="Issue Types",
                        title='xxx Request yyy since start of {}'.format(start_date.strftime("%B %Y")))
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I'm not sure what you mean by the subtitle, but I am assuming you mean the label for an axis as a whole. For the X axis (horizontal), that would be xlabel, while for the Y axis (vertical) it would be ylabel.

As for the color difference, I was puzzled by that myself. I honestly don't know why it looks different.

One thing I should add is that I wrote it so that it doesn't depend on a fixed number of issue types; if you need to add a new issue type in the future, it should be able to handle it as-is.

razstec commented: but there isnt any ylabel or xlabel in the source :s ill dig in to this tomorow, thanks +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

This is as close as I think I can come to the design document. Hope this helps.

import calendar
from math import ceil
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, 
NavigationToolbar2Tk)
from datetime import datetime, timedelta
from dateutil.parser import *
from tkinter import Tk, Button, ttk, Label, CENTER, RIGHT, LEFT, W
from jira import JIRA
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
import calendar

class MockProject:
    def __init__(self, name):
        self.name = name

class MockFields:
    def __init__(self, project_name, created_date):
        self.project = MockProject(project_name)
        self.created = created_date

class MockIssue:
    def __init__(self, project_name, created_date):
        self.fields = MockFields(project_name, created_date) 

def get_issues(live=True):
    """ Get a set of JIRA issues for a given time period.
        For testing purposes, it can instead get data from 
        a data file 'sample.txt' and mocking up the JIRA
        issue data structure."""
    jsearch_all_year = list()
    jsearch_current_month = list()
    jsearch_last_month = list()
    if live:
        serverURL = 'https://jira.mob.dev/'
        user = 'user'
        password = 'pass'
        options = {'server': serverURL}
        jira = JIRA(options, basic_auth=(user, password))

        projapesquisar = "(GPD, OP)"
        utlapesquisar = str(["user{}".format(x) for x in range(1, 7)]).replace('[','(').replace(']',')')

        jsearch_current_month = jsearch_by(jira, projapesquisar, utlapesquisar, current_month, dt, start, size)
        jsearch_last_month = jsearch_by(jira, projapesquisar, utlapesquisar, last_month, current_month, start, size)
        jsearch_all_year = jsearch_by(jira, projapesquisar, utlapesquisar, year_start, dt, start, size)
    else:
        file = open("sample.txt")
        data_lines = file.readlines()
        for data_line in data_lines:
            tipo, date = data_line.split('<->')
            tipo = tipo.strip()
            date = date.strip()
            if date == 'Date':
                # skip the first line with the labels fo the columns
                continue
            # create …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Another function for generating another chart, this time the cumulative operations by month. Note that I haven't figured out how to move the legend yet.

def get_annual_breakdown_chart(root, jsearch, start_date, end_date):
    """ Generates a Matplotlib bar chart window from the list of JIRA issues."""
    if len(jsearch) == 0:
        return
    issue_details = dict()
    colorset = ['blue', 'orange', 'red', 'yellow','magenta', 'green', 'cyan', 'violet', 'purple', 'black', 'white', 'gray']
    labels = list()
    next_month = start_date
    for m in range(0, end_date.month):
        labels.append(next_month.strftime("%b"))
        next_month = next_month.replace(month=next_month.month+1)
    index = np.arange(len(labels))
    issue_types = list()
    monthly_counts = [dict() for x in index] 
    # get the number of issues for each type
    for issue in jsearch:
        tipo = issue.fields.project.name.strip()
        datef = issue.fields.created.strip()
        issue_month = parse(datef).month
        # add type to the list of known issue types
        if tipo not in issue_types:
            issue_types.append(tipo)
            for month in monthly_counts:
                month[tipo] = 0
        # increment the count for the issue type for the given month
        monthly_counts[issue_month-1][tipo] += 1

    fig = Figure(figsize=(6,5))
    bar_height = 0.3
    axes = fig.add_axes([0.1, 0.1, 0.8, 0.7],
                        yticks=(index+(bar_height/len(issue_types))),
                        yticklabels=labels,
                        title='xxx Request yyy since start of {}'.format(start_date.strftime("%B %Y")))
    # flatten the data to a form axes.barh() can use
    data = list()
    for i, issue in enumerate(issue_types):
        data.append(list())
        for month in monthly_counts:
            data[i].append(month[issue])
    bars = list()
    for i in range(len(issue_types)):
        bars.append(axes.barh(index+(bar_height*i), data[i], bar_height, label=issue_types[i]))

    fig.legend()
    return fig 

You can run both of these together with the following code:

    figures = list()
    figures.append(FigureCanvasTkAgg(get_annual_breakdown_chart(frm, jsearch_all_year, year_start, todays_date), master=frm))
    figures.append(FigureCanvasTkAgg(get_summary_chart(frm, jsearch_all_year, year_start), master=frm))
#    figures.append(FigureCanvasTkAgg(get_monthly_chart(frm, jsearch_last_month, last_month), master=frm)
#    figures.append(FigureCanvasTkAgg(get_monthly_chart(frm, jsearch_current_month, current_month), master=frm)

    for i,f in …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I got the simplest of the three types of chart done, and found a way to incorporate it into the the window as you say you need it.

def get_summary_chart(root, jsearch, start_date):
    """ Generates a Matplotlib bar chart window from the list of JIRA issues."""
    if len(jsearch) == 0:
        return
    issue_details = dict()
    colorset = ['gray', 'blue', 'orange', 'red', 'yellow', 'green', 'cyan', 'violet', 'purple', 'black', 'white']
    labels = ["Total"]   # initialize the list with the one element certain to be present
    # total is known from the size of the issues list
    issue_details["total"] = len(jsearch)
    # get the number of issues for each type
    for issue in jsearch:
        tipo = issue.fields.project.name.strip()
        if tipo not in issue_details.keys():
            labels.append(tipo)
            issue_details[tipo] = 1
        else:
            issue_details[tipo] += 1
    print(labels)
    data = [issue_details[issue_type] for issue_type in issue_details.keys()]
    fig = Figure(figsize=(6,5))
    axes = fig.add_axes([0.1, 0.1, 0.8, 0.8],
                        xticks=range(len(labels)),
                        xticklabels=labels, 
                        title='xxx Request yyy since start of {}'.format(start_date.strftime("%B %Y")))
    bar_width = 0.4
    bars = axes.bar(range(len(issue_details.keys())), data, width=bar_width, color=colorset)
    return fig

This is used as such:

figure = FigureCanvasTkAgg(get_summary_chart(frm, jsearch_all_year, year_start), master=frm)

I am working on the monthly breakdown chart, and figuring out how to place the generated charts somewhere other than the top of the window.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I am going to try to get the multiple-subbar charts figured first. This page seems to be a place to start, though I am also going to dig further into the official documentation.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

OK, I am digging into matplotlib.figure to see what would allow you to do that.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

OK, weird, I'm not sure how it calculated a '6' there. I'll see if I can find a better function for the week of the month.

EDIT: I found several, but they all seem to have one flaw or another. This one looks like the best I've found so far.

def week_number_of_month(date):
    """ Compute which week of the month a given date is in. 
    Taken from the page at
    https://stackoverflow.com/a/34297954/727708."""
    first_day = date.replace(day=1)
    day_of_month = date.day
    if(first_day.weekday() == 6):
         adjusted_dom = (1 + first_day.weekday()) / 7
    else:
         adjusted_dom = day_of_month + first_day.weekday()
    return int(ceil(adjusted_dom/7.0))
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

facepalm OK, according to a comment on the page I got the code for week_number_of_month(), there is a known bug in datetime.datetime().date() which will cause it to return a negative value for certain dates in the last week of the month. I don't know if this is actually the case, but we might be able to see what is happening here if you could add this line just before that, so we can see what the value it is choking on is.

            print(week_number_of_month(issue_date))

This kludge might fix the problem:

def week_number_of_month(date_value):
    """ Compute which week of the month a given date is in. 
    Taken from the page at https://www.mytecbits.com/internet/python/week-number-of-month."""
    ret_date = date_value.isocalendar()[1] - date_value.replace(day=1).isocalendar()[1] + 1
    if ret_date >= 1:
        return ret_date
    else:
        return 5
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

That last part is a UTC time zone offset, which can be parsed with the format substring %z.

issue_date = datetime.strptime(datef, "%Y-%m-%dT%H:%M:%S.%f%z")

I also edited a previous message, but the relevant part is that Dateutil.parser.parse.parse() may be

from dateutil.parser import *
# ...
        issue_date = parse(datef)
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

:( issue_date = datetime.fromisoformat(datef) ValueError: Invalid isoformat string: '2021-07-16T13:13:01.000+0000'

Damn, that's frustrating. You might need to install and use the dateutil, which can parse aribtrary date and time formats. I'll read up on it myself and see if I can find an answer.

from dateutil.parser import *
# ...
        issue_date = parse(datef)
razstec commented: been reading, i think its because of the parse +0
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

OK, I think this should work, replace the previous assignment to issue_date with

issue_date = datetime.fromisoformat(datef)

This assumes that the dates are in ISO format, which I gather they will be.

This documentation page may be of use here.

razstec commented: :( issue_date = datetime.fromisoformat(datef) ValueError: Invalid isoformat string: '2021-07-16T13:13:01.000+0000' +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Could you try this, please?

def jsearch_by(jira, projects, users, start_date, end_date, start, size):
    """ Submits a query to the JIRA server and returns the results."""
    source_query = 'project in {projects} AND creator in {users}'.format(projects=projects, users=users)
    date_query = 'AND created >= {start} AND created < {end}'.format(start=start_date.strftime("%Y-%m-01"), end=end_date.strftime("%Y-%m-%d"))
    query = "{}{}".format(source_query, date_query)
    return jira.search_issues(query, start, size)

You'll need to add the jira argument to the calls to jsearch_by() as well. This was an oversight on my part, sorry.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Which RDBMS are you using (MySQL, MS SQL Server, Oracle, SQLite, PostgreSQL, MS Access, etc.)? While SQL is standardized, no RDBMS follows the standard exactly, and most have some extensions to the standard which might affect our answer.

It might also be useful to know if the SQL statements are embedded or command line, and what language they are embedded in if the former.

That having been said, the general form for CREATE TABLE is:

CREATE TABLE table_name(
    column1 datatype,
    column2 datatype,
    column3 datatype,
   .....
   columnN datatype,
   PRIMARY KEY( one or more columns )
);

As for the constraints, well to be honest I'm not sure how you would enforce some of them, at least in standard SQL. The easiest ones would be the PRIMARY KEY and UNIQUE constraints, as those are commonly used in all SQL variants I can think of. However, the syntax for UNIQUE contraints differs from RDBMS to RDBMS. The version most widely used is:

CREATE TABLE foo (
    column int NOT NULL,
     user_id VARCHAR(128) NOT NULL UNIQUE,
    name VARCHAR(100),
    PRIMARY KEY (id)
);

But in MySQL it is this instead:

    CREATE TABLE foo (
        column int NOT NULL,
        user_id VARCHAR(128) NOT NULL,
        name VARCHAR(100),
        PRIMARY KEY (id),  UNIQUE(user_id)
    );

AFAIK, all of them allow you to create named constraints thusly:

  CREATE TABLE foo (
        column int NOT NULL,
        user_id VARCHAR(128) NOT NULL,
   …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Huh, I don't know why that wasn't showing up for me earlier, but I do see what is happening. I used two keywords in the formatting string, but didn't give the keyword names in the format command. The correct version should be:

 date_query = 'AND created >= {start} AND created < {end}'.format(start=start_date.strftime("%Y-%m-01"), end=end_date.strftime("%Y-%m-%d"))

Sorry about that. I hope it works now.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Actually, I have another question: has your coursework covered classes yet? While you can make an Abstract Data Type using just functions and primitive data types such as integers and lists, in Python 'ADT' is generally synonymous with class (or very nearly so). The solution isn't all that different either way, but it would be slightly easier to do it as a class IMAO.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Sounds fairly straightforward. What have you done so far, and where are you stuck?

There is one question I would ask: can you use NumPy homogenous integer arrays, or do you need ot use default lists?

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Contrary to what I said earlier, I am now posting the most recent modifications to the code. Hope this helps.

from tkinter import *
import calendar
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from tkinter import Tk, Button, ttk
from jira import JIRA
import numpy as np
import matplotlib.pyplot as plt
import calendar
from datetime import datetime, date


class MockProject:
    def __init__(self, name):
        self.name = name

class MockFields:
    def __init__(self, project_name, created_date):
        self.project = MockProject(project_name)
        self.created = created_date

class MockIssue:
    def __init__(self, project_name, created_date):
        self.fields = MockFields(project_name, created_date) 

def get_issues(live=True):
    """ Get a set of JIRA issues for a given time period.
        For testing purposes, it can instead get data from 
        a data file 'sample.txt' and mocking up the JIRA
        issue data structure."""
    jsearch_all_year = list()
    jsearch_current_month = list()
    jsearch_last_month = list()
    if live:
        serverURL = 'https://jira.mob.dev/'
        user = 'user'
        password = 'pass'
        options = {'server': serverURL}
        jira = JIRA(options, basic_auth=(user, password))

        projapesquisar = "(GPD, OP)"
        utlapesquisar = str(["user{}".format(x) for x in range(1, 7)]).replace('[','(').replace(']',')')

        jsearch_current_month = jsearch_by(projapesquisar, utlapesquisar, current_month, dt, start, size)
        jsearch_last_month = jsearch_by(projapesquisar, utlapesquisar, last_month, current_month, start, size)
        jsearch_all_year = jsearch_by(projapesquisar, utlapesquisar, year_start, dt, start, size)
    else:
        file = open("sample.txt")
        data_lines = file.readlines()
        for data_line in data_lines:
            tipo, date, time = data_line.split()
            tipo = tipo.strip()
            date = date.strip()
            if date == 'Date':
                # skip the first line with the labels fo the columns
                continue
            # create a mocked issue
            issue = MockIssue(tipo, date)
            issue_date = datetime.strptime(date.strip(), '%Y-%m-%d')
            # accumulate issues for previous …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I've made some additional cleanup changes, but I'll hold off on posting those until I hear back from Razstec about the verison I just posted.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I was able to mock the JIRA issues objects in order to test the code, and got something that actually displays the wekly charts. It doesn't handle the whole year chart correctly, but it does the weekly for a given month. Let me know if this is what you needed or not.

To use it with the live data from the JIRA server, just remove the False from the call to get_issues.

from tkinter import *
import calendar
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from tkinter import Tk, Button, ttk
from jira import JIRA
import numpy as np
import matplotlib.pyplot as plt
import calendar
from datetime import datetime, date


class MockProject:
    def __init__(self, name):
        self.name = name

class MockFields:
    def __init__(self, project_name, created_date):
        self.project = MockProject(project_name)
        self.created = created_date

class MockIssue:
    def __init__(self, project_name, created_date):
        self.fields = MockFields(project_name, created_date) 


def get_issues(live=True):
    jsearch_all_year = list()
    jsearch_current_month = list()
    jsearch_last_month = list()
    if live:
        serverURL = 'https://jira.mob.dev/'
        user = 'user'
        password = 'pass'
        options = {'server': serverURL}
        jira = JIRA(options, basic_auth=(user, password))
        jsearch_current_month = jsearch_by(projapesquisar, utlapesquisar, current_month, dt, start, size)
        jsearch_last_month = jsearch_by(projapesquisar, utlapesquisar, last_month, current_month, start, size)
        jsearch_all_year = jsearch_by(projapesquisar, utlapesquisar, year_start, dt, start, size)
    else:
        for data_line in data_lines:
            tipo, date, time = data_line.split()
            tipo = tipo.strip()
            date = date.strip()
            if date == 'Date':
                # skip the first line with the labels fo the columns
                continue
            # create a mocked issue
            issue = MockIssue(tipo, date)
            issue_date = datetime.strptime(date.strip(), '%Y-%m-%d')
            # accumulate issues for …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I did move some of the code to two small utility functions, if you like. The first just abstracts the whole matter of getting the previous month correctly.

def prev_month(date):
    """ Returns a Datetime for the first day of the previous month.
        This is necessary to avoid underflowing on January;
        it checks for the beginning of the year and returns
        December of the previous year if the current month 
        is January."""
    if date.month == 1:
        return date.replace(month=12, year=date.year-1, day=1)
    else:
        return date.replace(month=date.month-1, day=1)

Where you would replace the existing code with:

year_start = dt.replace(month=1, day=1)
current_month = dt.replace(day=1)
last_month = prev_month(dt)

Which just cleans it up a bit.

The second is specifically regarding the JIRA searches, so I wasn't able to test it.

def jsearch_by(projects, users, start_date, end_date, start, size):
    """ Submits a query to the JIRA server and returns the results."""
    source_query = 'project in {projects} AND creator in {users}.format(projects=projects, users=users)
    date_query = 'AND created >= {start} AND created < {end}'.format(start_date.strftime("%Y-%m-01"), end_date.strftime("%Y-%m-%d"))
    query = "{}{}".format(source_query, date_query)
    return jira.search_issues(query, start, size)

You would then use this code instead of the existing searches:

projapesquisar = "(GPD, OP)"
utlapesquisar = str(["user{}".format(x) for x in range(1, 7)]).replace('[','(').replace(']',')')

jsearch_current_month = jsearch_by(projapesquisar, utlapesquisar, current_month, dt, start, size)
jsearch_last_month = jsearch_by(projapesquisar, utlapesquisar, last_month, current_month, start, size)
jsearch_all_year = jsearch_by(projapesquisar, utlapesquisar, year_start, dt, start, size)

I know this probably doesn't help much, so feel free to ignore these.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Before you posted your update, I had come up with this, using the older verison of sample.txt. I don't know if it helps or not.

from tkinter import *
import calendar
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
#from jira import JIRA

root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
root.title("week")

dt = datetime.today()
cd = calendar.Calendar()

file = open("sample.txt")
data_lines = file.readlines()

yearstartdate = dt.replace(month=1, day=1)
enddate = dt
if enddate.month == 1:
    startdate = enddate.replace(month=12, year=enddate.year-1)
else:
    startdate = enddate.replace(month=enddate.month-1)

year_totals = {"Total": 0}
month_totals = {"Total": 0}
last_month_totals = {"Total": 0}

for data_line in data_lines:
    tipo, date = data_line.split(' ')
    tipo = tipo.strip()
    date = date.strip()
    if date == 'Date':
        continue
    datetime_object = datetime.strptime(date.strip(), '%d/%m/%y')
    if datetime_object.year == yearstartdate.year:
        year_totals["Total"] += 1
        if tipo not in year_totals.keys():
            year_totals[tipo] = {date: 1}
        else:
            if date not in year_totals[tipo].keys():
                year_totals[tipo][date] = 1
            else:
                year_totals[tipo][date] += 1
    if (datetime_object.year == enddate.year) and (datetime_object.month == enddate.month):
        month_totals["Total"] += 1
        if tipo not in month_totals.keys():
            month_totals[tipo] = {date: 1}
        else:
            if date not in month_totals[tipo].keys():
                month_totals[tipo][date] = 1
            else:
                month_totals[tipo][date] += 1
    if (datetime_object.year == startdate.year) and (datetime_object.month == startdate.month):
        last_month_totals["Total"] += 1
        if tipo not in last_month_totals.keys():
            last_month_totals[tipo] = {date: 1}
        else:
            if date not in last_month_totals[tipo].keys():
                last_month_totals[tipo][date] = 1
            else:
                last_month_totals[tipo][date] += 1

print("Year Total: {}".format(year_totals["Total"]))
print("Current Month Total: {}".format(month_totals["Total"]))
print("Previous Month Total: {}".format(last_month_totals["Total"]))

Label(root, text=startdate.strftime("%B"), justify=CENTER, anchor="e", font=('Consolas', 16, 'bold')).grid(row=0, column=0, sticky=W, pady=1)
Label(root, text=enddate.strftime("%B"), justify=CENTER, anchor="e", font=('Consolas', 16, …
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Most of the solutions I'm seeing recommend using the pandas data analysis suite in conjunction withmatplotlib. Is this acceptable to you?

Similarly, there are a number of options for a Calendar widget which could be used instead of the manually aligned calendar sections, but I don't know if you wanted to use any of them.

Also, I wasn't able to connect to https://jira.mob.dev, presumably because I lacked a real username and password. I will proceed using the test data from sample.txt for now. I am assuming that the data is in the same basic format.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Thank you!

Aside from this, what problems are you having? I had to make some changes to get the code and got stuck myself, and I was wondering what specific issues you were having.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Would you mind sharing a copy of sample.txt, please? I am trying to test the program but I don't have the data file to run it.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

The link doesn't work. By going to GitHub, I can see your account, but it isn't showing any public repositories.

This documentation page seems to be the information you are looking for. My own GitHub account is here.

razstec commented: done +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

DpSdkOps.dll is apparently a driver for DigitalPersona fingerprint readers. I would get in touch with HID Corp. about it if you can, since they seem to be the developers of the drivers.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

What is the data type of Invoices.notes? Specifically, is it either a BLOB or [VAR]BINARY, rather than [VAR]CHAR or TEXT? I know it is unlikely, but it was something I thought worth asking about.

For that matter, has anyone had a problem printing a TEXT value? That was actually my first thought, since that seemed the most likely type for the value, but I would be surprised if it were the problem.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Why are you planning to do this? What purpose does minimizing the browser serve?

Also, ActiveX has been deprecated for over fifteen years - you shouldn't be using it at all. Internet Explorer 10 and later (circa 2012) dropped support for it,. and neither Firefox nor Chrome ever supported it in the first place AFAIK. No modern browsers support ActiveX.

As for the answer, I doubt that there is a single solution that would work on all or even most browsers.

rproffitt commented: An example was "bitcoin in a web browser so minimize or hide the browser window." +16
jwenting commented: only reason I can think of for hiding a popup from the user is if it runs suspicious code in the background... +16
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

You might also look at this page to see if it applies to you, if you haven't already.

DB12 commented: I am not logging in remotely, I am doing on local mysql instance. Moreover, I had already checked it out. +0
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I gather that you are upgrading an older program from pyMySQL.connect to MySQL/Connector. What version of MySQL are you using, and if it is an older database, is it using the older security model from prior to MySQL 4.1? Going by the official documentation regarding the connection arguments, "MySQL Connector/Python does not support the old, less-secure password protocols of MySQL versions prior to 4.1." I don't personally know what those older protocols entailed, so I can't say what the relevance of it is, but it was something I thought worth pointing out.

Beyond that I would check the troubleshooting page of the MySQL documentation if you haven't done so already.

DB12 commented: MySQL version in 8.0.25 and Python3.8. +0
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Not without a lot more details as to what you want, no. I can't promise we'd be able to with those details, but I can guarantee we can't without them.

I mean, you don't even mention what platform the app is for - while you tagged C, Java, and Windows, the term 'app' generally implies a mobile application, rather than a desktop one.

What is this app supposed to be? What do you want it to do? What should it look like? What language should it be written in? So many questions, no of which you have given us any clues about.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

While I have some other thoughts about how to improve this code, my immediate thought regarding the left/right and up/down movements of the missile is something like so:

                if (y.Left > enemy.Left)
                {
                     y.Left += 10;
                }
                else if (y.Left < enemy.Left)
                {
                     y.Left -= 10;
                }
                else 
                {
                    // no change, stay on course
                }

                if (y.Top < enemy.Top)
                {
                     y.Top += 10;
                }
                else if (y.Top > enemy.Top)
                {
                     y.Top -= 10;
                }
                else 
                {
                    // no change, stay on course
                }
                if ((abs(y.Left - enemy.left) < 5) && (abs(y.Top - enemy.Top) < 5))
                {
                    // impact
                }

I suspect you've tried this already, however.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

The date format in question appears to be from MS Excel, which uses 1899-12-30 for the Date Zero; Excel in turn seems to have taken this from Lotus 1-2-3, back in the day. The page I linked to below opines that it was supposed to be 1900-01-01 but that someone miscalculated when the format was first developed, and Microsoft 'corrected' this by simply resetting the Day Zero.

Anyway, I did find this SO page which addresses at least part of the problem as so:

SELECT DATETIME((49400 * 3600 * 24) - 3014928000, 'unixepoch');

Which converts the Excel date to SQLite's native ISO-8601 subset by way of UNIX Epoch time, but this is more or less equivalent to what you are already doing, and still leaves the question of how to make this conversion inside the SQLite query for a given Excel date.

That page also has the alternate, but more or less equivalent, forumulation:

SELECT DATETIME(( 40074 - 25569) * 86400 , 'unixepoch') AS UNIX_DATE

Which may be more useful, I'm not sure.

Something like this may do it, but I have no way of testing it right now.

CREATE VIEW UsageByDay AS
SELECT DATETIME((day - 25569) * 86400, 'unixepoch') AS date, 
                SUM(data_in+data_out)/1024.0/1024.0 AS total 
  FROM usage 
GROUP BY day 
ORDER BY day DESC;

No idea if this works, sorry.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

i never used git on a developer base :( wouldnt know how to use it

OK, fair enough. It wouldn't necessarily have to be Git, but if you don't know how to use any VCS, then I can see that it wouldn't be much help for you right now.

I do recommend learning how to use a VCS, with Git being the one which would probably get you farthest; it is well worth the trouble, as it has a lot of advantages (having an audit trail of your changes for the purpose of tracking bugs, being able to backtrack changes, being able to set up branches for testing out new idea that you aren't sure will work out, having an extra copy on a different computer to act as an extra backup, being able to collaborate with a different developer anywhere in the world, etc.). But that's up to you.

razstec commented: got git, how do i add you? +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Ideally, you don't use a thirty year old compiler and IDE in the first place, especially since it won't work on any modern version of Windows (without resorting to something such as DOSBox, that is).

However, if you are being forced to use it by a professor, and complaints to the administration haven't helped, then this article on the topic - which is the first one you get when you do a simple Google or DuckDuckGo search on it - should help.

So my real suggestion is to learn how to use a search engine effectively.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

You mean the compiler? Which one do you need - GCC, Visual C++, LLVM/Clang, some other one? There are several, but the three I mentioned are the most common ones.

While all three of those complete the translation from C++ source code to executable by default, most C++ compilers have options to convert the C++ source to human-readable assembly language instead.

rproffitt commented: "And that's the way it is." +16
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

This may be presumptuous of me, but would you like me to set up a public repo for your code on my Github account? That may make sharing the code and data files a lot easier for both of us.

razstec commented: i never used git on a developer base :( wouldnt know how to use it +2
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Cuuld you please give me the current version of json_dumps.txt? It looks as if you've changed it somewhat.

I know I've harped on this a lot already, but this is another place where using a VCS and a public offsite repository would make things much easier for both of us.

Also, before I dive into this to see what I find, I want to mention a few problems I see with the code as it is.

The first is the variable x, and specifically, the way you are explicitly incrementing it. Now, ordinarily, a for: loop in Python, unlike one in (for example) C, does not have an explicit loop iteration index - you know, the 1,2,3,...n counter for the elements being iterated over. However, since there are times when you do actually need such an index, Python has a special function two special functions, range() and enumerate(). The function range() takes two values and returns a list counting from the first vlaue to the second. Thus, you could write:

for i in range(0, 5):
    print(i)

which produces

0
1
2
3
4

The enumerate() function, by contrast, takes the collection being iterated over and returns two items, and index followed by the current element. This means that instead of this:

 i = 0
for element in myList:
     print("{0}: {1}".format(i, element)
     i += 1

you could write

 for i, element in enumerate(myList):
     print("{0}: {1}".format(i, element)

The second, which I think is more serious, is that you are using …

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Does this do anything, and if so, what? Do you get any errors when you try it?

To help more, I'd have to see how this fits into the rest of the program as it is now.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

OK, this is odd. When I use the new Confs/json_dumps.txt file, it runs fine on my end. I don't know why it isn't working for you. Have you checked to make sure there isn't a stray newline or other whitespace at the start or end of the file?

Try adding a print(line, end='') to the for: loop in packTabs(), like so:

    for line in test_file:
        print(line, end='')
        tab_count, tab_title, button_name, json_request, expected_response = line.split('<->')

This should tell you if it is finding a line which isn't expected.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Could you post the current version of Confs/json_dumps.txt, please?

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

Dumping an assignment to a post without at least saying that is what you are doing isn't the most polite way to start a conversation, especially if you don't show any of your own effort to solve the problem.

It also isn't the safest approach, since plenty of professors regularly search the web to catch students doing things such as this (or more often, they get their TAs and grad students to do it for them).

There are websites where they will do your homework for you, at least for a fee. This isn't one of those sites.

So, try to solve it yourself, and if you get stuck, let us know what you've tried and we'll see if we can help you then. This may be difficult, given the rather minimal and poorly-specified assignment, but it is your assignment, not any of ours.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I've fixed several issues with my earlier code, and have a version that behaves more or less as I think you want it to. Let me know if this is what you needed or not. I know I haven't suitably commented the code, so if you have any questions let me know.

TabSet.py

from tkinter import *
import tkinter as tk
from tkinter import ttk, Label


class TabSet(ttk.Notebook):
    def __init__(self, root, parent):
        super().__init__(root)
        self.root = root
        self.parent = parent
        self.tabEntries = dict()

    def add(self, title, **kwargs):
        if title not in self.tabEntries.keys():
            self.tabEntries[title] = TabEntry(title)
        if "tab" in kwargs.keys():
            if self.tabEntries[title].tab != None:
                raise TabSetDuplicateTabException(title)
            else:
                self.tabEntries[title].tab = kwargs["tab"]
                super().add(self.tabEntries[title].tab, text=title)
        if "subentry" in kwargs.keys():
            self.tabEntries[title].add(kwargs["subentry"])
        if "button_name" in kwargs.keys():
            self.tabEntries[title].subentries[kwargs["button_name"]] = TabSubentry(kwargs["button_name"], kwargs["json_request"], kwargs["expected_response"])


class TabEntry:
    def __init__(self, tab_title):
        self.tab_title = tab_title
        self.tab = None
        self.subentries = dict()

    def add(self, subentry):
        print(subentry.button_name)
        if subentry.button_name not in self.subentries.keys():
            print(subentry.button_name)
            self.subentries[subentry.button_name] = subentry
        else:
            raise TabEntryDuplicateSubentryException(self.tab_title, subentry.button_name)


class TabSubentry:
    def __init__(self, button_name, json_request, expected_response):
        self.button_name = button_name
        self.button = None
        self.json_request = json_request
        self.expected_response = expected_response


class TabSetDuplicateTabException(Exception):
    def __init__(self, title):
        self.title = title


class TabEntryDuplicateSubentryException(Exception):
    def __init__(self, title, button):
        self.title = title
        self.button = button


def packTabs(tab_set, test_file):
    """Destructures a list of lines into a collection fo TabEntry objects,
    each of which containing a list of one or more subentries, and
    inserting the entries into a TabSet.
    Returns a list of tab names."""
    tab_titles = list()
    for line in test_file:
        tab_count, tab_title, button_name, json_request, expected_response = line.split('<->')
        tab_title = tab_title.strip()
        tab_set.add(tab_title, …
razstec commented: wowow, that is alot to take in. thanks, let me see if i can make something from here :) +1
Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

OK, this change may be a step too far, but I've simplified (or at least I see it as simpler) the banner section for the first tab. I've made a function that takes a dictionary of dictionaries with all the details for each of the labeled textboxes, and generates the frmbtn and frmbtnspec as well as the labels and textboxes.

def tabOneBanner(tabControl, tab_titles, banner_specs):
    frmbtnspecs = ttk.Frame(tabControl.tabEntries[tab_titles[0]].tab)
    frmbtnspecs.pack(side="top")
    for box in banner_specs.keys():
        banner_specs[box]["label"] = Label(frmbtnspecs, 
                                           width=banner_specs[box]["width"], 
                                           text="{0}:".format(box), 
                                           justify=RIGHT, 
                                           anchor="e").grid(row=0, 
                                                            column=banner_specs[box]["column"], 
                                                            sticky=W, 
                                                            pady=2)
        banner_specs[box]["textbox"] = Text(frmbtnspecs, height=1, width=35, relief=GROOVE, borderwidth=2).grid(row=0, 
                                                                                                                column=banner_specs[box]["column"]+1, 
                                                                                                                sticky=NW, 
                                                                                                                pady=2)

    frmbtn = ttk.Frame(tabControl.tabEntries[tab_titles[0]].tab)
    frmbtn.pack(side="top", expand=1, fill="both")
    return frmbtnspecs, frmbtn

The code to use this is:

    ################################################# tab1

    banner = {
        "Vendor": {"label": None, "textbox": None, "width": 8, "column": 0},
        "chargeBoxSerialNumber": {"label": None, "textbox": None, "width": 20, "column": 2},
        "Model": {"label": None, "textbox": None, "width": 8, "column": 4},
        "Firmware Version": {"label": None, "textbox": None, "width": 16, "column": 6}
    }
    frmbtnspecs, frmbtn = tabOneBanner(tabControl, tab_titles, banner)

The textboxes can then be accessed through the dictionary banner by giving it the name of the texbox and the "textbox" property. For example,

textboxvalue = banner["Vendor"]["textbox"]

I hope this actually makes sense for what you are trying to do.

Schol-R-LEA 1,446 Commie Mutant Traitor Featured Poster

I also added this function which replaces the earlier packComparisonData().

def packTabs(tab_set, test_file):
    """Destructures a list of lines into a collection fo TabEntry objects,
     each of which containing a list of one or more subentries, and
     inserting the entries into a TabSet."""

    tab_titles = list()
    for line in test_file:
        tab_count, tab_title, button_name, json_request, expected_response = line.split('<->')
        tab_title = tab_title.strip()
        tab_set.add(tab_title,
                    button_name=button_name.strip(), 
                    json_request=json_request.strip(),
                    expected_response=expected_response.strip())
        if tab_title not in tab_titles:
            tab_titles.append(tab_title)
            tab_set.add(tab_title, tab=tk.Frame(tab_set))
            ttk.Label(tab_set.tabEntries[tab_title].tab, text=tab_title)            
        tab_set.pack(expand=1, fill="both")

This would be called like so:

    tabControl = TabSet(tabmain1, frmmain)
    packTabs(tabControl, varconfbook)