I am in transit so I don't have time for a lot of back and forth email relating to winreg. It also seems that there are a lot of people (let's call them "back seat coders") who have vague ideas of what they want but don't want to spend a bunch of time in a long discussion about registry arcana. Therefore I am endevouring to make it as easy and fast to contribute to the discussion as possible. I'm doing this through a Python Module Proposal format. This can also serve as the basis of documentation. This is really easy so I want some real feedback this time. Distutils people, this means you! Mark! I would love to hear Bill Tutt, Greg Stein and anyone else who claims some knowledge of Windows! If you're one of the people who has asked for winreg in the core then you should respond. It isn't (IMO) sufficient to put in a hacky API to make your life easier. You need to give something to get something. You want windows registry support in the core -- fine, let's do it properly. Even people with a minimal understanding of the registry should be able to contribute: the registry isn't rocket surgery. I'll include a short primer in this email. All you need to do is read this email and comment on whether you agree with the overall principle and then give your opinion on fifteen possibly controversial issues. The "overall principle" is to steal shamelessly from Microsoft's new C#/VB/OLE/Active-X/CRL API instead of innovating for Python. That allows us to avoid starting the debate from scratch. It also eliminates the feature that Mark complained about (which was a Python-specific innovation). The fifteen issues are mostly extensions to the API to make it easier (convenience extensions) or more powerful (completeness extensions). Many of them are binary: "do this, don't do that." Others are choices: e.g. "Use tuples", "Use lists", "Use an instance". I will try to make sense of the various responses. Some issues will have strong consensus and I'll close those quickly. Others will require more (hopefully not much!) discussion. Windows Registry Primer: ======================== There are things called "keys". They aren't like Python keys so don't think of them that way. Keys have a list of subkeys indexed by name. Keys also have a list of "values". Values have names. Every value has a type. In some type-definition syntax: key is (name: string, subkeys: (string : key), values: (string : value )) value is ( name: string, type: enumeration, data: (depends on enumeration) ) That's the basic model. There are various helper facilities provided by the APIs, but really, the model is as above. ========================================================================= Python Module Proposal Title: Windows registry Version: $Revision: 1.0$ Owner: paul@prescod.net (Paul Prescod) Python-Version: 2.0 Status: Incomplete Overview It is convenient for Windows users to know that a Python module to access the registry is always available whenever Python is installed on Windows. This is especially useful for installation programs. There is a Windows registry module from the win32 extensions to Python. It is based directly on the original Microsoft APIs. This means that there are many backwards compatibility hacks, "reserved" parameters and other legacy features that are not interesting to most Python programmers. Microsoft is moving to a higher level API for languages other than C, as part of Microsoft's Common Runtime Library (CRL) initiative. This newer, higher level API serves as the basis for the module described herein. This higher level API would be implemented in Python and based upon the low-level API. They would not be in competition: a user would choose based on their preferences and needs. Module Exports These are taken directly from the Common Runtime Library: ClassesRoot The Windows Registry base key HKEY_CLASSES_ROOT. CurrentConfig The Windows Registry base key HKEY_CURRENT_CONFIG. CurrentUser The Windows Registry base key HKEY_CURRENT_USER. LocalMachine The Windows Registry base key HKEY_LOCAL_MACHINE. CurrentUser The Windows Registry base key HKEY_CURRENT_USER. DynData The Windows Registry base key HKEY_DYN_DATA. PerformanceData The Windows Registry base key HKEY_PERFORMANCE_DATA. Users The Windows Registry base key HKEY_USERS. RegistryKey Registry key class (important class in module) RegistryKey class Data Members These are taken directly from the Common Runtime Library: Name Retrieves the name of the key. [Issue: full path or just name within parent?] SubKeyCount Retrieves the count of subkeys. ValueCount Retrieves the count of values in the key. RegistryKey Methods These are taken directly from the Common Runtime Library: Close() Closes this key and flushes it to disk if the contents have been modified. CreateSubKey( subkeyname ) Creates a new subkey or opens an existing subkey. [Issue: SubKey_full_path]: Should it be possible to create a subkey deeply: >>> LocalMachine.CreateSubKey( r"foo\bar\baz" ) Presumably the result of this issue would also apply to every other method that takes a subkey parameter. It is not clear what the CRL API says yet (Mark?). If it says "yes" then we would follow it of course. If it says "no" then we could still consider the feature as an extension. [Yes] allow subkey parameters to be full paths [No] require them to be a single alphanumeric name, no slashes DeleteSubKey( subkeyname ) Deletes the specified subkey. To delete subkeys and all their children (recursively), use DeleteSubKeyTree. DeleteSubKeyTree( subkeyname ) Recursively deletes a subkey and any child subkeys. DeleteValue( valuename ) Deletes the specified value from this key. __cmp__( other ) Determines whether the specified key is the same key as the current key. GetSubKeyNames() Retrieves an array of strings containing all the subkey names. GetValue( valuename ) Retrieves the specified value. Registry types are converted according to the following table: REG_NONE: None REG_SZ: UnicodeType REG_MULTI_SZ: [UnicodeType, UnicodeType, ...] REG_DWORD: IntegerType REG_DWORD_LITTLE_ENDIAN: IntegerType REG_DWORD_BIG_ENDIAN: IntegerType REG_EXPAND_SZ: Same as REG_SZ REG_RESOURCE_LIST: Same as REG_BINARY REG_FULL_RESOURCE_DESCRIPTOR: Same as REG_BINARY REG_RESOURCE_REQUIREMENTS_LIST: Same as REG_BINARY REG_LINK: Same as REG_BINARY??? [Issue: more info needed!] REG_BINARY: StringType or array.array( 'c' ) [Issue: REG_BINARY Representation]: How should binary data be represented as Python data? [String] The win32 module uses "string". [Array] I propose that an array of bytes would be better. One benefit of "binary" is that allows SetValue to detect string data as REG_SZ and array.array('c') as REG_BINARY [Issue: Type getting method] Should there be a companion method called GetType that fetches the type of a registry value? Otherwise client code would not be able to distinguish between (e.g.) REG_SZ and REG_SZ_BINARY. [Yes] Add GetType( string ) [No] Do not add GetType GetValueNames() Retrieves a list of strings containing all the value names. OpenRemoteBaseKey( machinename, name ) Opens a new RegistryKey that represents the requested key on a foreign machine. OpenSubKey( subkeyname ) Retrieves a subkey. SetValue( keyname, value ) Sets the specified value Types are automatically mapped according to the following algorithm: None: REG_NONE String: REG_SZ UnicodeType: REG_SZ [UnicodeType, UnicodeType, ...]: REG_MULTI_SZ [StringType, StringType, ...]: REG_MULTI_SZ IntegerType: REG_DWORD array.array('c'): REG_BINARY [Issue: OptionalTypeParameter] Should there be an optional parameter that allows you to specify the type explicitly? Presume that the types are constants in the winreg modules (perhaps strings or integers). [Yes] Allow other types to be specified [No] People who want more control should use the underlying win32 module. Proposed Extensions The API above is a direct transliteration of the .NET API. It is somewhat underpowered in some senses and also is not entirely Pythonic. It is a good start as a basis for consensus, however, and these proposed extensions can be voted up or down individually. Two extensions are just the convenience functions (OpenRemoteKey and the top-level functions). Other extensions attempt to extend the API to support ALL features of the underlying API so that users never have to switch from one API to another to get a particular feature. Convenience Extension: OpenRemoteKey It is not clear to me why Microsoft restricts remote key opening to base keys. Why does it not allow a full path like this: >>> winreg.OpenRemoteKey( "machinename", r"HKEY_LOCAL_MACHINE\SOFTWARE\Python" ) [Issue: Add_OpenRemoteKey]: [Yes] add RemoteKey [No] do not add? [Issue: Remove_OpenRemoteBaseKey] [Remove] It's redundant! [Retain] For backwards compatibility Convenience Extension: Top-level Functions A huge number of registry-manipulating programs treat the registry namespace as "flat" and go directly to the interesting registry key. These top-level functions allow the Python user to skip all of the OO key object and get directly to what they want: key=OpenKey( keypath, machinename=None ) key=CreateKey( keypath, machinename=None ) DeleteKey( keypath, machinename=None ) val=GetValue( keypath, valname, machinename=None ) SetValue( keypath, valname, valdata, machinename=None ) [Yes] Add these functions [No] Do not add [Variant] I like the idea but would change the function signatures Completeness Extension: Type names If the type extensions are added to SetValue and GetValue then we need to decide how to represent types. It is fairly clear that they should be represented as constants in the module. The names of those constants could be the cryptic (but standard) Microsoft names or more descriptive, conventional names. Microsoft Names: REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD REG_DWORD_LITTLE_ENDIAN REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR REG_RESOURCE_REQUIREMENTS_LIST Proposed Descriptive Names: NONE STRING EXPANDABLE_TEMPLATE_STRING BINARY_DATA INTEGER LITTLE_ENDIAN_INTEGER BIG_ENDIAN_INTEGER LINK STRING_LIST RESOURCE_LIST FULL_RESOURCE_DESCRIPTOR RESOURCE_REQUIREMENTS_LIST We could also allow both. One set would be aliases for the other. [Issue: TypeNames]: [MS Names]: Use the Microsoft names [Descriptive Names]: Use the more descriptive names [Both]: Use both Completeness Extension: Type representation No matter what the types are called, they must have values. The simplest thing would be to use the integers provided by the Microsoft header files. Unfortunately integers are not at all self-describing so getting from the integer value to something human readable requires some sort of switch statement or mapping. An alternative is to use strings and map them internally to the Microsoft integer constants. A third option is to use object instances. These instances would be useful for introspection and would have the following attributes: msname (e.g. REG_SZ) friendlyname (e.g. String) msinteger (e.g. 6 ) They would have only the following method: def __repr__( self ): "Return a useful representation of the type object" return "<RegType %d: %s %s>" % \ (self.msinteger, self.msname, self.friendlyname ) A final option is a tuple with the three attributes described above. [Issue: Type_Representation]: [Integers]: Use Microsoft integers [Strings]: Use string names [Instances]: Use object instances with three introspective attributes [Tuples]: Use 3-tuples Completeness Extension: Type Namespace Should the types be declared in the top level of the module (and thus show up in a "dir" or "from winreg import *") or should they live in their own dictionary, perhaps called "types" or "regtypes". They could also be attributes of some instance. [Issue: Type_Namespace]: [Module]: winreg.REG_SZ [Dictionary]: winreg.types["REG_SZ"] [Instance]: winreg.types["REG_SZ"] Completeness Extension: Saving/Loading Keys The underlying win32 registry API allows the loading and saving of keys to filenames. Therefore these could be implemented easily as methods: def save( self, filename ): "Save a key to a filename" _winreg.SaveKey( self.keyobj, filename ) def load( self, subkey, filename ): "Load a key from a filename" return _winreg.RegLoadKey( self.handle, subkey, filename ) >>> key.OpenSubKey("Python").save( "Python.reg" ) >>> key.load( "Python", "Python.reg" ) [Issue: Save_Load_Keys] [Yes] Support the saving and loading of keys [No] Do not add these methods Completeness Extension: Security Access Flags The underlying win32 registry API allows security flags to be applied to the OpenKey method. The flags are: "KEY_ALL_ACCESS" "KEY_CREATE_LINK" "KEY_CREATE_SUB_KEY" "KEY_ENUMERATE_SUB_KEYS" "KEY_EXECUTE" "KEY_NOTIFY" "KEY_QUERY_VALUE" "KEY_READ" "KEY_SET_VALUE" These are not documented in the underlying API but should be for this API. This documentation would be derived from the Microsoft documentation. They would be represented as integer or string constants in the Python API and used something like this: key=key.OpenKey( subkeyname, winreg.KEY_READ ) [Issue: Security_Access_Flags] [Yes] Allow the specification of security access flags. [No] Do not allow this specification. [Issue: Security_Access_Flags_Representation] [Integer] Use the Microsoft integers [String] Use string values [Tuples] Use (string, integer) tuples [Instances] Use instances with "name", "msinteger" attributes [Issue: Security_Access_Flags_Location] [Top-Level] winreg.KEY_READ [Dictionary] winreg.flags["KEY_READ"] [Instance] winreg.flags.KEY_READ Completeness Extension: Flush The underlying win32 registry API has a flush method for keys. The documentation is as follows: """Writes all the attributes of a key to the registry. It is not necessary to call RegFlushKey to change a key. Registry changes are flushed to disk by the registry using its lazy flusher. Registry changes are also flushed to disk at system shutdown. Unlike \function{CloseKey()}, the \function{FlushKey()} method returns only when all the data has been written to the registry. An application should only call \function{FlushKey()} if it requires absolute certainty that registry changes are on disk.""" If all completeness extensions are implemented, the author believes that this API will be as complete as the underlying API so programmers can choose which to use based on familiarity rather than feature-completeness. -- Paul Prescod - Not encumbered by corporate consensus "I don't want you to describe to me -- not ever -- what you were doing to that poor boy to make him sound like that; but if you ever do it again, please cover his mouth with your hand," Grandmother said. -- John Irving, "A Prayer for Owen Meany"
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4