Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
breaks
May 12, 2001

Boris Galerkin posted:

Oh okay. This made me reconsider about using properties to begin with. It just seems a bit weird that Python is "a consenting adults language" where nothing is private and everything can be accessed and used, yet @property exists to seemingly make things read-only.

You can make things read/write with properties, like @property, def whatever(self), @whatever.setter, def whatever(self, arg). But it's usually somewhat bad form to write something like that from the start. In most cases you would only do that for something that started out as a simple attribute and later needed to become more complicated without breaking user code (so seeing lots of @properties is often kind of symptom of something not being as well architected as it might have been).

Boris Galerkin posted:

I don't see any harm or why it's a bad idea to be able to do this:

I'm skeptical you can really construct a good argument for why jumping through hoops writing possibly buggy code that's irrelevant to the end functionality to enable this weird polymorphic construction, the semantics of which are basically foreign to python, is a big improvement on just typing ().

But if you have such an argument then lets hear it.

Adbot
ADBOT LOVES YOU

breaks
May 12, 2001

code:
>>> class Country:
	def __init__(self, names):
		self.names = names
	def name(self, language='en'):
		return self.names[language]
>>> belgium = Country({
    'en': 'Belgium',
    'de': 'Belgien',
    'nl': 'Belgie',
    'fr': 'Belgique'
})
Python 101 (not that this is some ideal production worthy idea or whatever), doesn't do anything weird/dumb, doesn't gently caress with the usual semantics of the language, Belgium is an instance of a Country class rather than the other way around, no separate 'default' entry in the dict that is arbitrarily in, and a duplicate of, English, etc etc

On the other hand, what you want to do is actually easy for trivial usage, so here is a way to implement this very, very, very bad localization mechanism (that probably still has some problems but it doesn't matter because you shouldn't do it anyway):

code:
>>> class PleaseDontDoThis(str):
	ohmygod = {
		'i promise this is bad': 'just because you can',
		'does not mean you should': 'trust me on this'
	}
	def __getitem__(self, thisisliterallysatan):
		return self.ohmygod[thisisliterallysatan]
>>> dontkickpuppies = PleaseDontDoThis('thats really mean')
>>> dontkickpuppies
'thats really mean'
>>> dontkickpuppies['i promise this is bad']
'just because you can'
(I know this is SA but I'm a softie so I've edited the latter bit to be less inflammatory, good luck and keep in mind that most the time, making the code work for you is really about making it easy enough to write and understand that you don't have to work for it.)

breaks fucked around with this message at 11:16 on Mar 10, 2017

breaks
May 12, 2001

I haven't looked at the implementation and I don't know anything about how such things usually work, but having read that I'd guess that's exactly what it means. With a system that can handle goofy stuff like int("9"*100000) it seems reasonable that it might make sense to convert to some ridiculous base like that so that a 16/32bit int is a digit. My guess would be they only use 15/30 bits of the number so that they can do normal math with the ints, peek at the most/two most significant bits, and handle carrying into the next digit with speed. Uh I guess I can't think of why 30 instead of 31 off the top of my head, but I'm sure there is some good reason.

Or I could be totally off base.

breaks fucked around with this message at 06:46 on Apr 7, 2017

breaks
May 12, 2001

Tigren posted:

Fluent Python has got me looking for tricks everywhere!

Python code:
        allowed_strings = ['Available Packages', 'Installed Packages', package_name]

        for line in out:
            if any([x in line for x in allowed_strings]):  #Ignores lines like 'Loaded plugins: fastestmirror'
                if 'Available Packages' in line:
                    add_to = available
                elif 'Installed Package' in line:
                    add_to = installed
                else:
                    add_to.append(line)

        return available, installed

1) There is a potential future problem that results from the string literals being duplicated in two different places.

2) What happens if package_name is seen before either of the strings?

3) Why is the if any line needed at all?

breaks
May 12, 2001

You're missing an 's' in the second installed packages line which is not immediately going to cause a problem but should probably be cleaned up.

You could turn the last else into an elif and then the any line is redundant.

Then your list can be turned into a list of categories instead of a list of categories and package names, and you can solve problem 1 by only having the category names in one place. As someone else suggested that place could also be a dict mapping category names to lists that you will append to.

breaks
May 12, 2001

Any of you dudes use an assertion library? I've looked at Sure and PyHamcrest and would be interested in alternatives, especially stuff with a different philosophy from those since they are a bit similar. This is for QA work, main goals are informative and readable errors and readability of the assertions themselves wrt less technical people.

breaks
May 12, 2001

If you do need to anchor it to the right your regexp itself is fine. Just modify filterSub and filterIP to take a string instead of a list then do this:

code:
def filter_all_this_shit(your_fucking_list):
   return [filterSub(some_fucked_up_domain) for some_fucked_up_domain in set(your_fucking_list) if filterIP(some_fucked_up_domain)]
Then your dict comprehension looks something like:

code:
groups = {key: filter_all_this_shit(domains) for key, domains in d.iteritems()}
You can iterate a set so no need to go list->set->list.

You could also use map or whatever else I guess, but personally in this kind of situation I almost always prefer giving a name to a comprehension like this. I think it's a lot more readable, assuming you aren't as big a fan of gratuitous profanity as I am.

breaks
May 12, 2001

It's so strange I hunted down the change. :shobon:

It's so you can do this:

code:
>>> d = OrderedDict(self=1)
>>> d
OrderedDict([('self', 1)])
A couple other things from collections work the same way for the same reason (as noted in the bug comments it's kind of pointless for OrderedDict). See: https://bugs.python.org/issue22609

breaks fucked around with this message at 00:00 on Apr 16, 2017

breaks
May 12, 2001

That's my understanding from that bug, yeah, but I don't know any more about it than that. But if you look through the changes made in that patch, that is the one that removed the self argument from __init__.

breaks fucked around with this message at 00:06 on Apr 16, 2017

breaks
May 12, 2001

I think what you are trying to do rarely makes sense. You should probably just write a method that calls whatever you want to call instead unless you have a really good reason not to. That said, why not just:

code:
>>> def f(self, arg):
	print(self.blah, arg)
>>> class A:
	def __init__(self):
		self.blah = 1
	meth = f
>>> a = A()
>>> a.meth(2)
1 2
If your concern is that "f" doesn't take self then replace with meth = staticmethod(f).

But again this situation should have every "there's got to be a better way" alarm in your head going off simultaneously.

breaks fucked around with this message at 04:48 on Apr 18, 2017

breaks
May 12, 2001

If the organizational issue is the only thing, just dump them in a class in the other file and inherit from it?

breaks
May 12, 2001

That is within the instance not the class. Functions in the class's namespace will work as methods (with maybe some exceptions if you really try to break it).

I know that's maybe kind of pedantic but that's the distinction that changes the behavior so...

breaks
May 12, 2001

Boris Galerkin posted:

The way I thought of it was that everything is being passed around by reference/pointer. So when I assign test.foo = foo what I'm actually doing is saying "hey test object, your memory location corresponding to "foo" is now pointing to this other memory location which happens to have information on how to execute the foo function.

I'm not sure if that's right or not but from a Fortran background it made perfect sense …

It is basically correct. As some of the previous posts were getting at, the Python function type implements the descriptor protocol. When you look up an attribute located in the class's namespace on a class or an instance of a class, if the object has a __get__ method, that's called and it's return value is what you get from the attribute lookup instead of the object itself. This is explained in more detail in the docs on the descriptor protocol. But point being, when you do Class.foo = some_function and then Class.foo or Class().foo, you are getting a newly created wrapper around the function and not the function itself.

Another fuckin edit to add: Today I also learned that this is changed from Python 2->3. In Python 2 you get an unbound method for the Class.foo lookup and in Python 3 you just get the function itself. But the descriptor mechanics are the same, what __get__ is returning is different.

Though again, unless this is just an experiment for learning about Python rather than actual in-use code, I think you are better off just calling the function with the instance as a parameter rather than doing the thing that we've had a 20-post discussion about the exact mechanics of.

More funny stuff:

code:
Illustrating the point about descriptors:

>>> class C:
	pass
>>> def f(arg):
	print("f")
>>> C.func = f
>>> inst = C()
>>> inst.func_ = f
>>> inst.func is f
False
>>> inst.func_ is f
True
>>> C.__dict__['func'] is f
True
>>> C.__dict__['func'].__get__(inst, C) is f
False

But this part surprised me:

>>> C.__dict__['func'].__get__(inst, C) is inst.func
False
>>> id(C.__dict__['func'].__get__(inst, C)) == id(inst.func)
True
In general the expectation is that id() == id() and is are equivalent. I think this happens basically because 1) you are getting a new method object each time __get__ is called and 2) the CPython implementation tries to cache the method object structure and reinitialize it with new data when it needs another one instead of allocating new memory each time. So in the id case presumably the method object from the call to __get__ gets deallocated when the id function call is over, the list pointer gets backed up one spot, and then the same structure in C is reinitialized with the data from the inst.func lookup. In CPython the object's location in memory is used for the id so they end up being the same. That seems to be the general idea anyway, I didn't go through it carefully enough to make sure that's 100% right.

Sorry I edited this a few times and search/replaced "c" with "inst" in the code because it was hard to read.

breaks fucked around with this message at 08:57 on Apr 19, 2017

breaks
May 12, 2001

I'm sorry-not-sorry to reiterate it again but keep in mind that doing self.something = types.MethodType(some_func, self) in __init__ or whatever does not exactly replicate the behavior of a normal method and with enough usage there will eventually be a situation where the fact that you have a MethodType in the instance namespace instead of a function in the class namespace becomes a problem even though it "works like a method."

If you don't care you don't care but do enough of this stuff and it will eventually bite you in the rear end in a very painful way unless you are really taking pains to exactly replicate the normal behavior. It is genuine Bad Python to drop a MethodType on an instance like that because it is subverting the expectations of the language implementation. I'll stop harping on it because I think I've said it too many times already.

breaks fucked around with this message at 10:29 on Apr 20, 2017

breaks
May 12, 2001

The descriptor howto is a great read and generally correct but has some simplifications, imprecise language, and outdated info. That code throws an exception on 3.6.1, and if you fix that the Class.Function lookup returns a bound method, etc etc; it isn't fully equivalent to how it actually works, at least not at this point.

Partial is fine. It's not pretending to be a method and then actually behaving in slightly different ways. But passing in the function and adding a method to call it with self is basically the same thing, and has already been suggested two or three times and the code written out for it at least once. The guy doesn't seem interested because it's not "injecting a method."

breaks
May 12, 2001

So basically what's happening there is that tkinter is only going to paint the GUI at some point in its event loop, but because that's one continuous section of code the event loop doesn't get a chance to execute until it's finished, leading to the behavior you see.

It's been way too long since I've used tkinter to offer a good solution but what you probably shouldn't do is try to force a paint in that code. This is a common situation and tkinter probably offers some Proper Way of allowing you to break that up so that the event loop gets to execute often enough to see your updates, which hopefully doesn't involve threading.

breaks
May 12, 2001

You need chromedriver for chrome, not geckodriver. I think you know this but just to clarify for the guy.

It isn't difficult to set up, just drop chromedriver in your working directory or path somewhere, pip install selenium and you should be good to go. If you have trouble try downgrading to selenium 3.0.2.

I'd recommend against geckodriver/Firefox with selenium for the time being unless you really need Firefox specifically, it's a half working mess right now as Mozilla is, to frame it positively, leading the charge on the transition to W3C webdriver standard.

breaks
May 12, 2001

Use the task scheduler unless you have a good reason not to. Running it in a loop will work until your computer reboots or it throws an exception and whatever series of other problems, then by the time you find and fix all those all you get for the extra work and inconvenience is probably a worse task scheduler.

breaks
May 12, 2001

I think your options are wxPython (which they have finally gotten around to cleaning up a bit) if you care about native elements, kIvy if you don't, or just do a web app with something that can fairly easily pack it up into a distributable binary (web2py, not sure if there are others).

breaks
May 12, 2001

You could just create the singleton and store it on the class in init and then have the instances proxy everything to it, or just access it through that attribute, or whatever you want. Maybe not ideal for performance in a game context but then neither is Python so...

If it's really needed you can customize instance creation with __new__ but I don't have much practical experience with it. And as always, mucking about with the machinery should really be a last resort...

breaks fucked around with this message at 20:51 on Aug 16, 2017

breaks
May 12, 2001

It's no big deal but you can provide a string as an argument to strip to tell it which characters you want to remove. So I'd probably do something like .strip(string.whitespace + "'") instead of .strip()[:-1] in a case like this.

It's not really needed for this simple case but if you don't mind installing something, the tool I like for simplifying the extraction of poo poo from random strings is parse. It basically lets you write a format string style specification of what you want to pull out, so you'd replace your sanitization and conversion work with something like parse.search('{:f}', some_string). Anyway it's very handy if you do a lot of this kind of stuff.

breaks fucked around with this message at 22:48 on Aug 26, 2017

breaks
May 12, 2001

If you have control over all the classes used, I think the Right Way is to call super().__init__ in every class in the hierarchy, and pass on arguments not used by the class using *args and **kwargs as necessary.

But this doesn't work if any one of the classes is not written with this technique in mind, in which case you need to revert to what you're already doing.

That said I try to avoid this kind of thing since traditional multiple inheritance kind of sucks, so maybe there is some better way that I don't know of.

Python3 ex:

code:
>>> class A:
	def __init__(self, pos1, **kwargs):
		print('A init')
		self.pos1 = pos1
		super().__init__(**kwargs)
>>> class B:
	def __init__(self, optional=None, **kwargs):
		print('B init')
		self.optional = optional
		super().__init__(**kwargs)
>>> class C(B, A):
	def __init__(self, pos1):
		print('C init')
		super().__init__(pos1=pos1)
>>> class D(A, B):
	def __init__(self, pos1):
		print('D init')
		super().__init__(pos1=pos1)
>>> class E(A, B):
	def __init__(self, pos1, **kwargs):
		print('E init')
		super().__init__(pos1=pos1, **kwargs)
>>> c = C(1)
C init
B init
A init
>>> d = D(1)
D init
A init
B init
>>> e = E(1, optional=True)
E init
A init
B init
>>> e.optional
True
Come to think of it, I guess in practice you probably want to avoid *args in the base classes and only call super().__init__ with keyword arguments along the lines of super().__init__(pos1=pos1, **kwargs), so I edited the code block to reflect that. But the point here is that super() means "the next thing in the MRO that implements this", so you call it in every class, take out what you need, and pass on the rest.

breaks fucked around with this message at 05:39 on Oct 11, 2017

breaks
May 12, 2001

As you say, from that code alone there is no reason len(pix) should increase. Absent any other information I'm going to guess the actual problem has to do with taking chunks of length L and incrementing your index by 1. If idx is 50 and rule.len is 100 and len(pix) is some large number, are you really intending to have chunks of pixels 50-149, 51-150, 52-151, etc?

If that's not it either I'm overlooking something or you need to provide more information.

If that is it, using names such as "chunk_length" instead of "l" or "position" instead of "idx" could help you avoid this kind of problem in the future. Having "i", "idx", "l", and "1" all in the same 10 lines of code is a bit gnarly. The loop appending pixel one at a time to chunk.ch also smells funny, it looks like a slice might be a good idea, but I don't know what pix and chunk.ch are exactly.

breaks fucked around with this message at 07:48 on Nov 29, 2017

breaks
May 12, 2001

So from your description it sounds as if you do intend to increment your index by l (the length of the current chunk) instead of 1 (as in the number). If you fix that does the current problem persist?

breaks
May 12, 2001

SnatchRabbit posted:

Right, but what I need is message to be this portion, in JSON, so I can use individual values (strings) like resourceID, and put that in a statement later. Not sure that makes sense, like I said I'm terrible with python.

As mentioned in the prior replies there isn't anything obviously wrong with your Python, but the example response you provided isn't consistent with the dict you pasted. For example, the JSON has a configRuleName key with a string value, and the dict has a configRuleNames key with a list of strings value (it only has one string). The structure of JSON example you gave is clearly not entirely the same as the structure of whatever JSON you are passing to json.loads.

I don't know much about AWS, but determining the cause of that discrepancy is where I would start.

breaks
May 12, 2001

Dr Subterfuge posted:

E3: using functools.wraps(func) as a decorator on newf is probably superior to just making the __doc__ attributes equal?

E4: If someone could explain how the args in the __init__ and __call__ methods are magically different (and why args in __init__ doesn't consume func) I'd be really interested to know. Because this still feels like witchcraft to me.

I don't comprehend at all what you're trying to accomplish. What you've got there at the moment seem to be one hell of a way to write self.some_list.append(some_stuff). On the other hand I've probably never manged to successfully understand a post in this thread when reading it at 2AM (or maybe ever) so I'll just answer these two specific questions:

Yes, if you're wrapping a function and want to make your wrapper appear to be what it's wrapping, use wraps.

The decorator syntax is only a shortcut for something that's otherwise ugly:

code:
def f(*args):
    print(*args)

f = decorator(f)  # If there was no @decorator syntax you would just write this
There is nothing magical about @decorator(a, b). Writing it out by hand results in a very literal translation:

code:
f = decorator(a, b)(f)
# or to really spell it out
actual_decorator = decorator_factory(a, b)
f = actual_decorator(f)


Disregarding multiple decorators and within the rather restrictive limits of what Python's grammar allows after the @, @X before f is the same as f = X(f) after it.

Does this help you understand what is going on? A decorator always gets called with one argument, which is the thing it's decorating. A "decorator with arguments" is a callable that returns a decorator. I think it's more clear to think of that as a decorator factory, but for whatever reasons the common terminology is just to lump it all together as "decorator". In what you wrote, __init__ is called as part of the process of instantiating the class. That's the factory part. Once the instance is created it's then called, which is possible since you defined __call__, and that's the decorator part.

breaks fucked around with this message at 08:42 on Apr 8, 2018

breaks
May 12, 2001

Dr Subterfuge posted:

Basically, I have some huge scraper functions that I'm trying to refactor into smaller components (with maybe the eventual goal of messing around with asyncio), and the structure I came up with was to turn each scraper into a class (or rather a subclass of a base scraper) and use attribute access in class methods. So I'm not really just appending things. It was mostly to illustrate that I want to be able to modify an existing value. I'm aware there are whole scraping packages like scrapy that have already solved most of these problems. I'm mostly just messing around with rolling something myself to see if I can learn anything in the process. (But one of those is getting better at designing things, so if there's a better way to go about updating a bunch of different fields in a data structure that would be cool to know.)

It sounds like the scrapers are mutating some shared data structure(s), but is that really necessary? Why not have each scraper do its scraping then return whatever data it gathered, which other parts of the program can then store or pass to other scrapers or whatever as needed? If you can reorganize things so that each scraper sticks to its scraping task and doesn't care about what happens to the scraped data, that will probably simplify the design of each component.

breaks
May 12, 2001

I didn't try it because I don't have Selenium up to date at home, but from looking at the page you probably want to hover the div.fn-show-login-tooltip element instead.

breaks
May 12, 2001

Sad Panda posted:

Thanks for the suggestion. Selenium seems to be going OK at the moment. Does Splinter click on elements that are not visible? That's one of the things that frustrates me with Selenium. I've got to insert some Javascript, to aria-hidden to false, or some other things.

Selenium/Webdriver's purpose is to emulate interacting with the browser as a user would, so you shouldn't need to click an element that isn't visible, because the user would actually be interacting with some other element instead of the hidden one.

YMMV for sites that are trying to deliberately break browser automation or otherwise doing something insane, but most of the time in this situation, you've either got the wrong element, or you've got the right element but aren't waiting for it to get into an interactable state.

If you want to provide some more information about the error, site, or whatever else is relevant, I'll be glad to have a look and see if anything pops out. A fair part of my job is dealing with this poo poo.

breaks fucked around with this message at 07:20 on May 24, 2018

breaks
May 12, 2001

Sad Panda posted:

Three examples of sites that refuse to work (claiming not visible/cannot focus) without some form of skullduggery include

Sorry for the late reply. I was under the weather for a couple days then had a lot of poo poo goin on what with the holiday.


Yeah, this is dumb. It just needs a click in the right spot to make the real input visible. If you really wanted to avoid the javascript you could click its parent element "div.username_wrap div.textboxex_Center". In some similar cases you might need ActionChains for more fine grained control over the click. But for your usage I think your js approach is actually the right thing to do. You're not trying to validate that this dual input UI implementation works normally, and it's surely less fragile than precise clicking.

quote:

2) https://www.kingjackcasino.com

The same issue. I can click on login, but then can't interact with the username field. I've tried
HTML code:
[class="login-box__input-wrapper"]
and the Chrome generated selector which is...
HTML code:
#ui-login-form > div:nth-child(1) > input[type="text"]

Actually a different issue. There are multiple elements matching both of those selectors and the first one it's finding in the DOM is not the one you want. "#login-modal input[placeholder="User Name / Email"]" is a pretty dumb selector but it gets the right one and I don't see a less fragile option at first glance.

quote:

3) Nationwide Online Banking. (https://onlinebanking.nationwide.co.uk/AccessManagement/Login). If you type in a random 10 digit customer number, click on Log in using memorable data, type a random thing into memorable data then the passnumber dropdowns become interactable. However, the dropdown values are hidden with aria-hidden = true
JavaScript code:
"document.getElementsByClassName('selection-list__value')[0].setAttribute('aria-hidden', 'false');"
That allows me to interact with them using Selenium.

Here the right thing to do is use selenium.webdriver.support.select.Select with the actual select element. Along the lines of this:

code:
from selenium.webdriver.support.select import Select
first_digit = Select(driver.find_element_by_css_selector('[name=FirstPassnumberValue]'))
first_digit.select_by_value('3')

breaks fucked around with this message at 06:09 on May 30, 2018

breaks
May 12, 2001

Yeah cross browser compatibility is better than it was a year ago but still has some issues. The transition to the w3c webdriver standard plus the slow pace of development on this stuff kind of threw a wrench in.

On my phone so I didn’t look at the page, but you might try move_to_element_with_offset using whatever container element for the game or even body, instead of move_by_offset.

breaks
May 12, 2001

Boris Galerkin posted:

I'm trying to play around with __getattr__ and __setattr__ so that I can do something like the following:

code:
    def __getattr__(self, k):
        # if self._whatever (OtherClass) has k then return self._whatever.k
        # elif self has k then return self.k
        # else raise error
e: I would like to avoid implementing @property and @setters for everything.

It was already mentioned but inside __getattr__ you need to call super().__getattr__ (pre-edit I said __getattribute__ here but I'm pretty sure that's incorrect - it's been a while though) to perform attribute access on self to avoid recursion. Similarly with super().__setattr__ if you want to set something on self in __setattr__. (I think super() is ok but it might be necessary to call them on object directly? I don't remember) Don't dig in the __dict__ directly unless you're absolutely sure you want to bypass basically all normal attribute access behavior.

Another thing to keep in mind is that __getattr__ is a fallback that only gets called when __getattribute__ fails (there is a little more to it than that, reference the Python Data Model document). Absent any shenanigans that means that the name wasn't found in the instance or class. So, checking for the name on self in __getattr__ does nothing.

If you're proxying a known thing and it's really just an issue of trying to avoid writing out 6 lines of getter and setter over and over, consider writing a factory function for your properties or your own property-like descriptor. Using a more narrowly targeted hook will save you headaches.

breaks fucked around with this message at 00:19 on Jul 7, 2018

breaks
May 12, 2001

Thermopyle posted:

This has always made me laugh.

"Let's write a bunch of useful and helpful code. Then lets take it and put it in the documentation instead of making it actually importable."

Brought to you by the makers of dataclasses, asyncio, mypy, and assignment expressions.

Smart people making reasonable decisions leads to astounding variety of useful and also very dumb poo poo.

breaks
May 12, 2001

I think that

code:
x = foo if b else bar
is the less head exploding way to write that in one line.

In general relying on False == 0 and True == 1 is bad.

breaks
May 12, 2001

Just use the soup's select method with a ".result-meta>.result-price" selector and call it a day. IMO always pick elements using CSS selectors up until they don't support what you need, that's what they were made for.

(On that page, there 221 matches for .result-price but 120 for .result-meta>.result-price. There are 120 items per page and at first glance the lower than expected number of .result-price results seems to be due to posts lacking pics only having the price displayed once? or something like that.)

breaks fucked around with this message at 08:13 on Dec 31, 2018

breaks
May 12, 2001

PBS posted:

Internally a number of people have just been disabling cert verification, which I'd like to help prevent.

if you don't trust anybody, you don't have to trust anybody *taps head*

breaks
May 12, 2001

I’d actually recommend against learning some other typed language and trying to apply it directly to Python. It’s just a little weird especially around stuff like mypy and pycharm compatibiltity, when to use interfaces vs I guess traditional types and so on. The hard stuff to understand about typing is things like, you have a class that is often subclassed and has some factory method in the superclass that returns an instance of whichever subclass, how do you write that out, and the complicated situations are just a bit WIP at the moment, particularly as I mentioned wrt things that are acceptable across various tools. Long story short due to newness and the language itself you need to learn to accept and work with python’s relatively fuzzy static typing concept.

breaks
May 12, 2001

What would you envision the difference between next and first being?

breaks
May 12, 2001

OnceIWasAnOstrich posted:

There are some situations where it will be very handy, and a whole bunch of examples that make me angry to look at.

I think they took a few of the more egregious examples out of the pep but early on there was sure some wow really!? stuff in there.

It does clean up some situations real nice though. :shrug:

Adbot
ADBOT LOVES YOU

breaks
May 12, 2001

I don’t know much about containers and so take this with a grain of salt, but as a general concept roughly I think you can think of it as virtualization of the OS rather than virtualization of the hardware.

breaks fucked around with this message at 18:58 on Apr 10, 2019

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply