Using Python datetime instead of Zope DateTime - python

https://pypi.python.org/pypi/DateTime mentions that it is better to use python datetime rather than Zope DateTime. I believe this is done by invoking External Methods. Is there any other way of doing this as I don't think one would like to create an external method for all the kind of stuff that needs to be imported ?

The class DateTime from module DateTime can be imported in the Zope restricted mode simply because it's declared as public in the package AccessControl. In its top level __init__.py
ModuleSecurityInfo('DateTime').declarePublic('DateTime')
It also contain this to allow import from four other utility builtin imports
for name in ('string', 'math', 'random', 'sets'):
ModuleSecurityInfo(name).setDefaultAccess('allow')
So to do so, you need to add similar lines to the __init__.py of your Zope package (or create one if you haven't already, see this tutorial), for instance:
from AccessControl import ModuleSecurityInfo
# just a specific class
ModuleSecurityInfo('datetime').declarePublic('datetime')
# or at a broader level for the entire module
ModuleSecurityInfo('datetime').setDefaultAccess('allow')
This of course assumes the package datetime is trusted enough to not be able to result in an attack against your Zope instance.

just for the record, I had this error when using strftime in a TAL expression (RestrictedPython) :
The container has no security assertions.
Access to 'strftime' of datetime.datetime(2021, 1, 31, 0, 0) denied.
I solved this by using allow_type from AccessControl :
from AccessControl import allow_type
from datetime import datetime
allow_type(datetime)
Gauthier

Related

use method of library imported in another module

In first.py, I imported the datetime library and called a method which is written in second.py. The method works well without importing the datetime libirary in second.py.
first.py
from datetime import datetime
import second
def method1(time):
return datetime.strptime(time,"%Y/%m/%d")
a = method1("2019/08/01")
b = second.method2(a)
second.py
def method2(para1):
return para1.second
Output
0
Should second.py import datetime so that para1.second can work? Can someone help explain the rationale behind?
You only need to import modules explicitly when you need to use their names. In first.py, for example, you're using things in the datetime module directly, and referring to it by name. So, you do import datetime, and then call datetime.strptime() on that module you imported.
In second.py, however, you don't have to do import datetime. This is because of how python handles attributes - when you do para1.second, python doesn't need to know exactly what type of variable para1 is - it just checks to see whether it has a field called second. And it does, so it returns that. Nowhere in second.py are you referring to datetime directly - only indirectly, via a variable that was defined from it.
Also consider that the datetime module does a lot of stuff on its own, and almost certainly imports other dependencies that you're not aware of and you're not importing yourself. But you can still use the datetime module, because you don't need to explicitly refer to those modules it's using behind the scenes. They're still in memory somewhere, and if you call certain methods from datetime, that code will still get executed, but you don't need to be directly aware of it.
Python usually uses duck typing1. This means that instead of requiring a particular type for an object, it looks at the actual attributes it has.
What this means in your case is that method2 does not care in the slightest whether you pass in a datetime object or not. All that's required is that the input para1 have a second attribute.
Importing datetime into second.py would be counter-productive. It wouldn't affect the operation of your method in any way, but it would polute your namespace and set up an implication that isn't necessarily true.
1 A notable counterexample is a sum of strings, e.g. sum(['a', 'b'], ''). Aside from that, your own code can choose what to do as you see fit if course.

Integrate class attributes in client namespace

I want to define a bunch of attributes for use in a module that should also be accessible from other modules, because they're part of my interface contract.
I've put them in a data class in my module like this, but I want to avoid qualifying them every time, similar to how you use import * from a module:
#dataclass
class Schema:
key1='key1'
key2='key2'
and in the same module:
<mymodule.py>
print(my_dict[Schema.key1])
I would prefer to be able to do this:
print(my_dict[key1])
I was hoping for an equivalent syntax to:
from Schema import *
This would allow me to do this from other modules too:
<another_module.py>
from mymodule.Schema import *
but that doesn't work.
Is there a way to do this?
Short glossary
module - a python file that can be imported
package - a collection of modules in a directory that can also be imported, is technically also a module
name - shorthand for a named value (often just "variable" in other languages), they can be imported from modules
Using import statements allows you to import either packages, modules, or names:
import xml # package
from xml import etree # also a package
from xml.etree import ElementTree # module
from xml.etree.ElementTree import TreeBuilder # name
# --- here is where it ends ---
from xml.etree.ElementTree.TreeBuilder import element_factory # does not work
The dots in such an import chain can only be made after module objects, which packages and modules are, and names are not. So, while it looks like we are just accessing attributes of objects, we are actually relying on a mechanism that normal objects just don't support, so we can't import from within them.
In your particular case, a reasonable solution would be to simply turn the object that you wanted to hold the schema into a top-level module in your project:
schema.py
key1 = 'key1'
key2 = 'key2'
...
Which will give you the option to import them in the way that you initially proposed. Doing something like this to make common constants easily accessible in your project is not unusual, and the django framework for example uses a settings.py in the same manner.
One thing you should keep in mind is that names in python modules are effectively singletons, so their values can't be changed at runtime[1].
[1] They can, but it's so hacky that it should pretty much always be treated as not possible.

Does importing specific class from file instead of full file matters?

Most of the tutorials and books about Django or Flask import specific classes from files instead of importing the whole file.
For example, importing DataRequiered validator from wrtforms.validators is done via from wtforms import validators instead of importing it via import wtforms.validators as valids and then accessing DataRequiered with valids.DataRequiered.
My question is: Is there an reason for this ?
I thought to something like avoiding the loading a whole module for computation/memory optimization (is it really relevant?) ? Or is it simply to make the code more readable ?
My question is: Is there an reason for this ?
from module_or_package import something is the canonical pythonic idiom (when you only want to import something in your current namespace of course).
Also, import module_or_package.something only works if module_or_package is a package and something a submodule, it raises an ImportError(No module named something) if something is a function, class or whatever object defined in module_or_package, as can be seen in the stdlib with os.path (which is a submodule of the os.package) vs datetime.date (which is a class defined in the datetime module):
>>> import os.path as p
>>> p
<module 'posixpath' from '/home/bruno/.virtualenvs/blook/lib/python2.7/posixpath.pyc'>
vs
>>>import datetime.date as d
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named date
thought to something like avoiding the loading a whole module for computation/memory optimization (is it really relevant?)
Totally irrelevant - importing a given name from a module requires importing the whole module. Actually, this:
from module_or_package import something
is only syntactic sugar for
import module_or_package
something = module_or_package.something
del module_or_package
EDIT: You mention in a comment that
Right, but importing the whole module means loading it to the memory, which can be a reason for importing only a submodule/class
so it seems I failed to make the point clear: in Python, you can not "import only a submodule/class", period.
In Python, import, class and def are all executable statements (and actually just syntactic sugar for operation you can do 'manually' with functions and classes). Importing a module actually consists in executing all the code at the module's top-level (which will instanciate function and class objects) and create a module object (instance of module type) which attributes will be all names defined at the top-level via import, def and class statements or via explicit assignment. It's only when all this has been done that you can access any name defined in the module, and this is why, as I stated above,
from module import obj
is only syntactic sugar for
import module
obj = module.obj
del module
But (unless you do something stupid like defining a terabyte-huge dict or list in your module) this doesn't actually take that much time nor eat much ram, and a module is only effectively executed once per process the first time it's imported - then it's cached in sys.modules so subsequent imports only fetch it from cache.
Also, unless you actively prevents it, Python will cache the compiled version of the module (the .pyc files) and only recompile it if the .pyc is missing or older than the source .py file.
wrt/ packages and submodules, importing a submodule will also execute the package's __init__.py and build a module instance from it (IOW, at runtime, a package is also a module). Package initializer are canonically rather short, and actually quite often empty FWIW...
It depends, in the tutorial that was probably done for readability
Usually if you use most of the classes in a file, you import the file. If the files contains many classes but you only need a few, just import those.
It's both a matter of readability and optimization.

how to directly import now() from datetime.datetime submodule

Background: I have a few tight loops in a Python program that are called repeatedly, which include the datetime.datetime.now() method, as well as the datetime.datetime.min and datetime.datetime.max attributes. For optimization, I would like to import them into the local namespace, avoiding the repeated, unnecessary module hierarchy name look-up, like so:
from datetime.datetime import now, min, max
However, Python complains:
Traceback (most recent call last):
File "my_code.py", line 1, in <module>
from datetime.datetime import now, min, max
ImportError: No module named datetime
Question: Why doesn't the above submodule import work?
Workaround: I can instead do this:
import datetime
dt_now = datetime.datetime.now
dt_min = datetime.datetime.min
dt_max = datetime.datetime.max
But, I'm curious why the more traditional approach does not work? Why can I not import methods and properties directly from the datetime.dateime submodule? ... And, is there any reason to avoid the above workaround (besides readability, outsmarting myself, etc.)?
Thanks!
datetime.datetime is not a submodule. datetime is a class within the datetime module. now is a method of that class. You can't use from...import... to import individual methods of a class. You can only use it to import individual modules from a package, or individual objects that exist at the top level of a module.
As for your workaround, if you want shorthand, I find it more readable to do this:
from datetime import datetime as dt
dt.now()
# you can also use dt.max, dt.min, etc.
If you really want to put those methods directly in local variables, then your workaround makes sense.

Syntax for importing function from object in class (Python 2)

I want to be able to access the strptime function directly (no datetime.datetime.strptime() or datetime.strptime().)
I can do this:
from datetime import datetime
strptime = datetime.strptime
But is there a way to accomplish the same thing on the import line?
Also, can you do multiple items on one line?
Here's pseudocode of what I really want to do:
from datetime.datetime import strftime, strptime
Datetime is just the example case, a similar thing would be useful for importing class methods in other libraries.
Those are methods of the datetime type and can't be imported directly. You can't directly import anything below the top-level namespace of a module. From the documentation:
The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1) [i.e., the module being imported], and binds the name in the local namespace to the object thus found.
That is, the imported names must be names in the module namespace. They can't be any more deeply nested than that. So you can't, as you apparently want to do, import just certain methods of classes in the module.
The answer to the question "Can I do this on the import line?" is no.
See the definition of the import statement in Python 2. The statement imports things from modules. There is a datetime class inside the datetime module. The best you can do is
from datetime import datetime
You already understand well what this does, as you used it perfectly in your question. It looks like you wanted to do
from datetime import datetime.strptime
but that is a syntax error because datetime.strptime is not an indentifier.
You can't say
from datetime.datetime import strptime
either because Python would look for a module named datetime.datetime.
The import statement just doesn't work the way you want it to.
Note that the author of the datetime module chose to make strptime a classmethod (using #classmethod) rather than a function. So if you want to use strptime without the class qualifier you will have to do what you did, namely assign to a variable named strptime.

Categories