0

I have an object class that takes sidewalk data and parses it for a transportation model.

At one point in the model, it uses a function of the sidewalk width and the pavement conditions to generate a score. This is relevant because the width and pavement condition score are handled exactly the same way throughout the process, but sidewalk_width initializes as an int, and sidewalk_score initializes as a NoneType.

Since it's a NoneType, nothing that's assigned to it seems to stick, so it keeps returning as None, even when I see a value should have been assigned.

The Sidewalk() class object is generated with the code below:

class Sidewalk(object):
    def __init__(self, **kwargs):
        self.sidewalk_width = kwargs.get("sidewalk_width")
        self.sidewalk_score = kwargs.get("sidewalk_condition_score")

The specific records are assigned with the block below:

def get_plts(path):
    with fiona.open(path, 'r', layer='plts') as src:
        driver = src.driver
        crs = src.crs
        schema = src.schema
        for f in src:
            data = f['properties']
            sidewalks = [Sidewalk(
                    sidewalk_width=data['sidewalk_width'],
                    sidewalk_score=data['sidewalk_condition_score'])]

And they ultimately get run through the function below:

    def _calculate_condition_score(self, sidewalk):
        width = sidewalk.sidewalk_width
        cond = sidewalk.sidewalk_score

Before they're initialized, the script can read the numbers from the geopackage without any problems. Both the width and the condition score are both assigned as integers in the geopackage. If a street has no sidewalk, Width will report as "None" for that record only, then continue operating correctly with an actual integer value, where the Condition score is always "None" regardless.

Why is width coming across intact from start to finish, where the condition seems to be locked in as NoneType?

I've plugged print statements throughout the model and found that the problem is happening at or around the time of initialization. By the time the model is actually working with the data, the type issue has already taken effect and the numbers for the condition score will only report as "Null".

  • 3
    The keyword argument you are passing is `sidewalk_score=....`, but you use `kwargs.get("sidewalk_condition_score`. So of course, it will default to `None`. **Why are you even using `**kwargs`** here? Why not just explicity name the arguments, then the function call would have raised an error instead of silently failing... or at lest use `kwarg['sidewalk_condition_score']` so then it will fail there – juanpa.arrivillaga Apr 05 '23 at 19:27
  • 2
    Don't use `**kwargs` if you already know what keyword arguments you expect. `def __init__(self, *, sidewalk_width, sidewalk_condition_score)`. – chepner Apr 05 '23 at 19:28
  • The main reason all of it is formatted as **kwargs currently is that this is a model that was used a few years ago at my organization, but everyone involved in it has left with little documentation supporting the project. I've been hesitant to change anything, just because then if I run into issues I can't be sure what I caused, but I can absolutely change how those are set up. – armchairavenger Apr 05 '23 at 19:42
  • Well, then I would go with @chepner suggestion, although just a head's-up, it isn't easy to tell what the rest of the code base will be expecting, i.e. in other places people may have passed the argument as `sidewalk_condition_score=....`. Refactoring won't be amenable to static analysis, all of this is why this should have never been designed this way in the first place. – juanpa.arrivillaga Apr 05 '23 at 19:51
  • 1
    @juanpa.arrivillaga Absolutely. I went ahead and changed the kwargs to match what it currently says, and it's producing the same results it did five years ago, which is good, but my first priority is going to be restructuring those inputs to something less prone to issues. It was something I should have been aware of, but I do appreciate the feedback that everyone gave. – armchairavenger Apr 05 '23 at 20:47

1 Answers1

0

In the data dictionary, the score is stored in the 'sidewalk_condition_score' key, but since you passed the kwarg as sidewalk_score=data['sidewalk_condition_score'], the score becomes stored in the "sidewalk_score" key. To access it, you want to write kwargs.get("sidewalk_score")

SimonUnderwood
  • 469
  • 3
  • 12
  • That was absolutely it. There were other issues elsewhere in the script where I think "sidewalk_score" was also getting re-used, but this fixed it. – armchairavenger Apr 05 '23 at 20:47