问:
h3Line function throws LineUndefinedException
I want to calculate index of the h3 cells between (-39.08, -57.01) and (-38.05, -58.16) but it throws LineUndefinedException.

In the documentation it says

This function may fail to find the line between two indexes, for example if they are very far apart. It may also fail when finding distances for indexes on opposite sides of a pentagon.

I think that it throws the exception because of the latter case. Is there workaround to calculate those cell indexes?

Code:

```<code>public static void main(String[] args) {
  try {
    H3Core h3Core = H3Core.newInstance();
    long p1 = h3Core.geoToH3(-39.08, -57.01, 8);
    long p2 = h3Core.geoToH3(-38.05, -58.16, 8);
    List<Long> line = h3Core.h3Line(p1, p2);
  } catch (Exception e) {
    e.printStackTrace();
  }
}
</code>```

Exception:

```<code>com.uber.h3core.exceptions.LineUndefinedException: Could not compute line size between cells
at com.uber.h3core.H3Core.h3Line(H3Core.java:630)
</code>```

答:
You have hit one of the edge cases H3 does not handle (yet), points on opposite sides of a pentagon:

The image above shows the edges of the icosahedron the H3 grid is based on. Pentagons are located at the vertexes of the icosahedron, and your points cross these edges in a way that makes it harder to compute the grid path.

The correct workaround here, which we eventually intend to implement in the library, is to find the intersection points between the great arc linking the two points and the icosahedron edges. To do this, you'd need the icosahedron geometry, which is available in the H3 lib but slightly hard to extract. There's a version here which has a bunch of unnecessary intermediate points in each edge (to facilitate rendering great arcs correctly on web maps), but which should work. The basic algorithm is:

Find all intersection points along the great arc between point A and point B.

For each point, find the H3 index.

Find the h3Line between each segment, e.g. h3Line(cellA, cellIntersection1), h3Line(cellIntersection1, cellIntersection2), and so on.

Combine the lines, dropping duplicate indexes.

There is likely an easier option here, which is to do the same thing but instead of calculating indexes just sample along the great arc. In this particular case, it looks like you probably could just take the center of the great arc and calculate h3Line twice, but in some cases you'd need more samples.

Body:
I want to calculate index of the h3 cells between (-39.08, -57.01) and (-38.05, -58.16) but it throws LineUndefinedException.

In the documentation it says

This function may fail to find the line between two indexes, for example if they are very far apart. It may also fail when finding distances for indexes on opposite sides of a pentagon.

I think that it throws the exception because of the latter case. Is there workaround to calculate those cell indexes?

Code:

public static void main(String[] args) {
  try {
    H3Core h3Core = H3Core.newInstance();
    long p1 = h3Core.geoToH3(-39.08, -57.01, 8);
    long p2 = h3Core.geoToH3(-38.05, -58.16, 8);
    List<Long> line = h3Core.h3Line(p1, p2);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

Exception:

com.uber.h3core.exceptions.LineUndefinedException: Could not compute line size between cells
at com.uber.h3core.H3Core.h3Line(H3Core.java:630)


来源: stackexchange

问:
Msbuild CLI platform=x64 and project file property <Platform>x64</Platform> give different results
This question is about the difference between using /p:Platform=x64 on the MSBuild command line versus using <Platform>x64</Platform> in the csproj file.

I made two simple c# NET 5 solutions/projects with one executable (HsConsole) and one class library (HsLogger) to investigate when MSB3270 architecture mismatches occurred. Here is an example error message.

```<code>warning MSB3270: There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "HsLogger", "AMD64".
</code>```

** Note the error message talks about MSIL (hsconsole) and AMD64 (hslogger), even though both the command line and project file specify x64 and NOT AMD64.

The HsLogger logger uses a post-build event to copy the class library to a folder that stores libraries for sharing among projects. The HsConsole project references the class library HsLogger from that folder.

The problem is that I get the MSB3270 error message (when compiling HsConsole) whenever I use /p:"Platform=x64" on the MSbuild command line, but not when I use no arguments on the command line. <Platform>x64</Platform> is already declared in the HsLogger project file in both cases.

Here are the two project files:

```<code>HsLogger
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <Platform>x64</Platform>
      <TargetFramework>net5.0-windows7.0</TargetFramework>
   </PropertyGroup>
</Project>

HsConsole
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <Platform>AnyCPU</Platform>
      <TargetFramework>net5.0-windows7.0</TargetFramework>
   </PropertyGroup>
</Project>
</code>```

Here is a summary of experimental results:

```<code>MSBuild hslogger.csproj /t:clean;restore;build -> compiles okay
MsBuild hsconsole.csproy /t:clean;restore;build -> no MSB3270 error

MSBuild hslogger.csproj /t:clean;restore;build /p:Platform=x64 -> compiles okay
MsBuild hsconsole.csproj /t:clean;restore;build -> gives MSB3270 error as shown above
</code>```

** Note the error message talks about MSIL (hsconsole) versus AMD64 (hslogger).

Q1. Why is AMD64 in the error message when only x64 is used?

Q2. Why is an error message being produced at all when the command line and internal property both specify x64?

答:
I carefully inspected the batch file output of the MSBuild command used to execute the commands shown above. In particular, the huge csc compiler command issued by MSBuild contains the argument /p:Platform=x64 only when the argument /p:Platform=x64 is provided on the command line.

The csc compiler command does NOT contain the x64 argument specified in the csproj file if no argument is given on the command line. In other words, the <Platform>x64</Platform> property in the project file does not cause MSBuild to pass x64 to the compiler command. That was unintuitive to me. My expectation was that <Platform>x64</Platform> in the project file would pass x64 to the compiler was not correct.

Then in the project file, I changed <Platform>x64</Platform> to <PlatformTarget>x64</PlatformTarget> and the x64 argument was passed to the compiler as /p:Platform=x64 (note: the argument passed to the compiler was Platform and not PlatformTarget).

Finally, when /p:PlatformTarget=x64 was given on the Msbuild command line, it produced the same results as <PlatformTarget>x64</PlatformTarget> in the project file alone. In both these cases, the MSB3270 occurred because the class library was compiled as x64 whereas the hsconsole program (that consumed the library) was compiled as AnyCPU.

Takeaways

<Platform> and <PlatformTarget> in the project file are two different things. The <Platform> value is used by the Clean target to delete folders but is NOT passed to the compiler. In contrast, the value of <PlatformTarget> is translated to /p:Platform=value, is passed to the compiler, and controls the type of output binary created by the compiler.

PlatformTarget is not even listed in the Common MSBuild project properties page, even though it is the definitive XML element that is passed to the csc compiler.
https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties

/p:Platform=value on the command line, /p:PlatformTarget=value on the command line, and <PlatformTarget>value</PlatformTarget> in the project file are all the same thing for compilation purposes. They all cause the value to be passed to the compiler.

My guess for the AMD64 part of the error message is that it comes from my dev computer, which contains an AMD CPU processor on the motherboard.

ContentLicense: CC BY-SA 4.0

Body:
This question is about the difference between using /p:Platform=x64 on the MSBuild command line versus using <Platform>x64</Platform> in the csproj file.

I made two simple c# NET 5 solutions/projects with one executable (HsConsole) and one class library (HsLogger) to investigate when MSB3270 architecture mismatches occurred. Here is an example error message.

warning MSB3270: There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "HsLogger", "AMD64".

** Note the error message talks about MSIL (hsconsole) and AMD64 (hslogger), even though both the command line and project file specify x64 and NOT AMD64.

The HsLogger logger uses a post-build event to copy the class library to a folder that stores libraries for sharing among projects. The HsConsole project references the class library HsLogger from that folder.

The problem is that I get the MSB3270 error message (when compiling HsConsole) whenever I use /p:"Platform=x64" on the MSbuild command line, but not when I use no arguments on the command line. <Platform>x64</Platform> is already declared in the HsLogger project file in both cases.

Here are the two project files:

HsLogger
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <Platform>x64</Platform>
      <TargetFramework>net5.0-windows7.0</TargetFramework>
   </PropertyGroup>
</Project>

HsConsole
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <Platform>AnyCPU</Platform>
      <TargetFramework>net5.0-windows7.0</TargetFramework>
   </PropertyGroup>
</Project>

Here is a summary of experimental results:

MSBuild hslogger.csproj /t:clean;restore;build -> compiles okay
MsBuild hsconsole.csproy /t:clean;restore;build -> no MSB3270 error

MSBuild hslogger.csproj /t:clean;restore;build /p:Platform=x64 -> compiles okay
MsBuild hsconsole.csproj /t:clean;restore;build -> gives MSB3270 error as shown above

** Note the error message talks about MSIL (hsconsole) versus AMD64 (hslogger).

Q1. Why is AMD64 in the error message when only x64 is used?

Q2. Why is an error message being produced at all when the command line and internal property both specify x64?


问:
Selenium WebDriver Very Slow to Append WebElement Data to List
I'm trying to store webelement content to a python list. While it works, it's taking ~15min to process ~2,000 rows.

```<code># Grab webelements via xpath
rowt = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/th[@class='listing-title']")
rowl = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/td[@class='listing-location']")
rowli = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/th/a")

title = []
location = []
link = []

# Add webElement strings to lists
print('Compiling list...')
[title.append(i.text) for i in rowt]
[location.append(i.text) for i in rowl]
[link.append(i.get_attribute('href')) for i in rowli]
</code>```

Is there a faster way to do this?

答:
Using bs4 would definitely help.
Even if you may have to find elements again using bs4, it was still faster to use bs4.
I'd like to suggest you try bs4.

I.e., code like this would work

```<code>soup = bs4.BeautifulSoup(driver.page_source, "html.parser")
elements = soup.find_all(...)
Loop using i
    Some job using elements[i]['target attribute']
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I'm trying to store webelement content to a python list. While it works, it's taking ~15min to process ~2,000 rows.

# Grab webelements via xpath
rowt = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/th[@class='listing-title']")
rowl = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/td[@class='listing-location']")
rowli = driver.find_elements_by_xpath("//tbody[@class='table-body']/tr/th/a")

title = []
location = []
link = []

# Add webElement strings to lists
print('Compiling list...')
[title.append(i.text) for i in rowt]
[location.append(i.text) for i in rowl]
[link.append(i.get_attribute('href')) for i in rowli]

Is there a faster way to do this?

Body:
Using bs4 would definitely help.
Even if you may have to find elements again using bs4, it was still faster to use bs4.
I'd like to suggest you try bs4.

I.e., code like this would work

soup = bs4.BeautifulSoup(driver.page_source, "html.parser")
elements = soup.find_all(...)
Loop using i
    Some job using elements[i]['target attribute']


问:
Python/OpenSSL issue: ERROR:root:code for hash md5 was not found
This error occurred while installing latest Ruby using ruby-install.

What I tried:

brew switch openssl <my_version>

brew upgrade openssl

And many other solutions that were proposed in SO. None solved my problem.

答:
So the problem is actually coming that python2 is not supported, but you can solve it by installing just correct openssl via brew, e.g.

brew install openssl@1.1


问:
How to parameterize ports for docker-compose?
I am trying to parameterize a docker-compose file using .env. Doc

docker-compose.yml

```<code>version: '2.3'
networks:
    default: { external: true, name: $NETWORK_NAME }
services:
    rabbitmq_local:
        image: 'rabbitmq:3.6-management-alpine'
        ports:
          # The standard AMQP protocol port
          - ${RABBIT_PORT}:5672
          # HTTP management UI
          - '15672:15672'
</code>```

.env file

```<code>NETWORK_NAME=uv_atp_network
RABBIT_PORT=5672
RABBIT_HTTP_MANAGEMENT_PORT=15672
</code>```

Parameterizing NETWORK_NAME works, but parameterizing RABBIT_PORT doesn't, with

```<code>The Compose file 'docker-compose.yml' is invalid because:
services.rabbitmq_local.ports contains an invalid type, it should be a number, or an object
</code>```

This makes me suspect RABBIT_PORT is interpreted as string rather than a number.

How can I parameterize it correctly?

EDIT

I found that forcing the variable to be mandatory

```<code>- ${RABBIT_PORT:?unspecified_rabbit_port}:5672
</code>```

gives the error, meaning it is unset or empty.

What am I doing wrong?

答:
It seems that when running with pytest and pytest-docker-compose the .env file has to be in the root folder of pytest, along with the pytest.ini file.

Running from docker-compose from command-line doesn't have that limitation in docker 1.24.

After relocating the file, the variables could be resolved.

Body:
I am trying to parameterize a docker-compose file using .env. Doc

docker-compose.yml

version: '2.3'
networks:
    default: { external: true, name: $NETWORK_NAME }
services:
    rabbitmq_local:
        image: 'rabbitmq:3.6-management-alpine'
        ports:
          # The standard AMQP protocol port
          - ${RABBIT_PORT}:5672
          # HTTP management UI
          - '15672:15672'

.env file

NETWORK_NAME=uv_atp_network
RABBIT_PORT=5672
RABBIT_HTTP_MANAGEMENT_PORT=15672

Parameterizing NETWORK_NAME works, but parameterizing RABBIT_PORT doesn't, with

The Compose file 'docker-compose.yml' is invalid because:
services.rabbitmq_local.ports contains an invalid type, it should be a number, or an object

This makes me suspect RABBIT_PORT is interpreted as string rather than a number.

How can I parameterize it correctly?

EDIT

I found that forcing the variable to be mandatory

- ${RABBIT_PORT:?unspecified_rabbit_port}:5672

gives the error, meaning it is unset or empty.

What am I doing wrong?


问:
Explode Array Element into a unique column
I'm new to Pyspark and trying to solve an ETL step.

I have the following schema below. I would like to take the variable that is inside the array and transform it into a column, but when doing this with explode I create duplicate rows because there are positions [0], [1], and [2] inside the element.

My goal is to transform what is inside variable into a new column taking everything that is in the element (separating by comma what was in each element) and transforming it into a string.

```<code>root
 |-- id: string (nullable = true)
 |-- info: array (nullable = true)
 |    |-- element: struct (containsNull = false)
 |    |    |-- variable: string (nullable = true)
</code>```

Output:

id
new column

123435e5x-9a9z
A, B, D

555585a4Z-0B1Y
A

Thank you for the help

答:
As mentioned by David Markovitz you can use the concat_ws function as below:</p>
```<code>from pyspark.sql import functions as F
(df.withColumn('new column', F.concat_ws(', ', F.col('info'))
</code>```

Body:
I'm new to Pyspark and trying to solve an ETL step.

I have the following schema below. I would like to take the variable that is inside the array and transform it into a column, but when doing this with explode I create duplicate rows because there are positions [0], [1], and [2] inside the element.

My goal is to transform what is inside variable into a new column taking everything that is in the element (separating by comma what was in each element) and transforming it into a string.

root
 |-- id: string (nullable = true)
 |-- info: array (nullable = true)
 |    |-- element: struct (containsNull = false)
 |    |    |-- variable: string (nullable = true)

Output:

id
new column

123435e5x-9a9z
A, B, D

555585a4Z-0B1Y
A

Thank you for the help

Body:
As mentioned by David Markovitz you can use the concat_ws function as below:

from pyspark.sql import functions as F
(df.withColumn('new column', F.concat_ws(', ', F.col('info'))


问:
AWS SAM app API multiple method declarations
I created AWS sam application. It has a REST API customers. Presently I'm able to add only one http method type either GET or POST.

```<code>AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ""

Globals:
Function:
Timeout: 59

Resources:
  HealthFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: index.handler
      Runtime: nodejs14.x
      Architectures:
        - x86_64
      Events:
        Health:
          Type: Api
          Properties:
            Path: /health
            Method: get
        Customers:
          Type: Api
          Properties:
            Path: /customers
            Method: get

Outputs:
  HealthApi:
    Description: "API Gateway endpoint URL for Prod for Health function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/health"
  CustomersApi:
    Description: "API Gateway endpoint URL for Prod for Health function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/customers"
</code>```

How can I declare customers API http methods both GET and POST?

答:
You can define multiple events for the same path.

```<code>CustomersGetEvent:
  Type: Api
  Properties:
    Path: /customers
    Method: GET
CustomersPostEvent:
  Type: Api
  Properties:
    Path: /customers
    Method: POST
</code>```

As an alternative you can also use Method: ANY.

Body:
I created AWS sam application. It has a REST API customers. Presently I'm able to add only one http method type either GET or POST.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ""

Globals:
Function:
Timeout: 59

Resources:
  HealthFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: index.handler
      Runtime: nodejs14.x
      Architectures:
        - x86_64
      Events:
        Health:
          Type: Api
          Properties:
            Path: /health
            Method: get
        Customers:
          Type: Api
          Properties:
            Path: /customers
            Method: get

Outputs:
  HealthApi:
    Description: "API Gateway endpoint URL for Prod for Health function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/health"
  CustomersApi:
    Description: "API Gateway endpoint URL for Prod for Health function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/customers"

How can I declare customers API http methods both GET and POST?

Body:
You can define multiple events for the same path.

CustomersGetEvent:
  Type: Api
  Properties:
    Path: /customers
    Method: GET
CustomersPostEvent:
  Type: Api
  Properties:
    Path: /customers
    Method: POST

As an alternative you can also use Method: ANY.


问:
SQLAlchemy: How do you delete multiple rows without querying
I have a table that has millions of rows. I want to delete multiple rows via an in clause.  However, using the code:

```<code>session.query(Users).filter(Users.id.in_(subquery....)).delete()
</code>```

The above code will query the results, and then execute the delete.  I don't want to do that. I want speed.

I want to be able to execute (yes I know about the session.execute):Delete from users where id in ()

So the Question: How can I get the best of two worlds, using the ORM? Can I do the delete without hard coding the query?

答:
New syntax (1.4 version and above)

from sqlalchemy import delete

statement = delete(User).where(User.id.in_(...))
session.exec(statement) # sync syntax
# session.execute(statement) # async syntax
```

https://docs.sqlalchemy.org/en/14/core/dml.html?highlight=delete

Body:
I have a table that has millions of rows. I want to delete multiple rows via an in clause.  However, using the code:

session.query(Users).filter(Users.id.in_(subquery....)).delete()

The above code will query the results, and then execute the delete.  I don't want to do that. I want speed.

I want to be able to execute (yes I know about the session.execute):Delete from users where id in ()

So the Question: How can I get the best of two worlds, using the ORM? Can I do the delete without hard coding the query?

Body:
New syntax (1.4 version and above)

from sqlalchemy import delete

statement = delete(User).where(User.id.in_(...))
session.exec(statement) # sync syntax
# session.execute(statement) # async syntax

https://docs.sqlalchemy.org/en/14/core/dml.html?highlight=delete


问:
Integration test `enterText` method not working on profile or release mode
Test passes in debug mode but not in profile or release mode. It does not enter text when calling enterText even if the input has focus. In debug mode it enters the text without problems.

答:
This is an issue, or more exactly a difference between how integration-tests work in debug vs profile or release.

TLDR

Basically if you're not in debug mode you have to call binding.testTextInput.register() in order for tester.enterText to work.

```<code>  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;

// Necessary for being able to enterText when not in debug mode
  binding.testTextInput.register();
</code>```

This will permit to call enterText during integration testing.
As a caveat this will disable the use of real keyboards during the test, but most of the times that is not the case.

Why does that happens?

Because in debug mode this is permitted via an assert which don't work on profile or release modes. See source code

Body:
This is an issue, or more exactly a difference between how integration-tests work in debug vs profile or release.

TLDR

Basically if you're not in debug mode you have to call binding.testTextInput.register() in order for tester.enterText to work.

  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;

// Necessary for being able to enterText when not in debug mode
  binding.testTextInput.register();

This will permit to call enterText during integration testing.
As a caveat this will disable the use of real keyboards during the test, but most of the times that is not the case.

Why does that happens?

Because in debug mode this is permitted via an assert which don't work on profile or release modes. See source code


问:
Comparing Partial Matches in Two Lists
Use Case:

I'm trying to take two lists a, and b and search for a partial domain match. Then if a value is matched it should be excluded from the third list. For all non matches I want to grab the .id and insert them into f

Example:

For example I've got list a with a bunch of data that looks like the below. I want to take the hostname field from a and search it against list b, where we should find test.online in this example. Once we find that we should discard it. I want to append the .id to f for anything that doesn't have a match. Hopefully that makes sense.

```<code>a = [{'hostname': 'apache.test.online',
      'id': '20c073b2-245e-410b-8a29-4440d4669987']}

b = ['test.online', 'google.com']

f = []
for i in b:
  for j in a:
    if j.hostname in i.domain:
      f.append(i)
result = list(set(f))
</code>```

I'm new so I've been stuck on this for about a day now. My last attempt is above. I appreciate any input! Thanks!

答:
Like this?

result = [
    h['id']
        for h in a
        if not any(d in h['hostname'] for d in b)
]
```

Title: Comparing Partial Matches in Two Lists

Body:
Use Case:

I'm trying to take two lists a, and b and search for a partial domain match. Then if a value is matched it should be excluded from the third list. For all non matches I want to grab the .id and insert them into f

Example:

For example I've got list a with a bunch of data that looks like the below. I want to take the hostname field from a and search it against list b, where we should find test.online in this example. Once we find that we should discard it. I want to append the .id to f for anything that doesn't have a match. Hopefully that makes sense.

a = [{'hostname': 'apache.test.online',
      'id': '20c073b2-245e-410b-8a29-4440d4669987']}

b = ['test.online', 'google.com']

f = []
for i in b:
  for j in a:
    if j.hostname in i.domain:
      f.append(i)
result = list(set(f))

I'm new so I've been stuck on this for about a day now. My last attempt is above. I appreciate any input! Thanks!


问:
Date format issue in Pyspark
I have an issue with formatting the date.

The actual value for the date is 2021/12/28

I am trying to format it to 20211228 with the following code

awardTypeDFrame = awardTypeDFrame.withColumn('ACTIONDATE', sf.date_format(sf.col('pyresolvedtimestamp'), 'YYYYMMdd'))

which gives me 20221228. So, basically it rounds off the year to 2022 from 2021. I have been trying to figure out why would this happen but could not find an explanation for it. Do you have any idea why it does not pick the right year ? Please let me know . Thanks for your time from now

答:
The code snippet you shared is correct , however the pattern you are using is incorrect

The available DateTime Patterns for Parsing can be found - https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html

Date Format

```<code>awardTypeDFrame = awardTypeDFrame.withColumn('ACTIONDATE', sf.date_format(sf.col('pyresolvedtimestamp'), 'yyyyMMdd'))
</code>```

Title: Date format issue in Pyspark

Body:
The code snippet you shared is correct , however the pattern you are using is incorrect

The available DateTime Patterns for Parsing can be found - https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html

Date Format

awardTypeDFrame = awardTypeDFrame.withColumn('ACTIONDATE', sf.date_format(sf.col('pyresolvedtimestamp'), 'yyyyMMdd'))


问:
Null pointer exeception in ListAdapter
I want to display Data in List View but I got Error Null Pointer Exception run time in line

```<code>fList.setAdapter(la);
</code>```

My code is here List is complete printing in Log
Thanks

```<code>public class Forfattere extends Activity {
/** Called when the activity is first created. */
ArrayList<String> aList = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.forfattere);
    ListView fList = (ListView)findViewById(R.id.Author_list);
    ArrayList<String> a = DBlistbookfestival.getAuthorName();
    for(int i=0;i<a.size();i++){
        aList.add(a.get(i));
        Log.v("all_data",a.get(i));
    }
    ListAdapter1 la = new ListAdapter1(this, R.id.Author_list, aList);
    fList.setAdapter(la);
 }

private class ListAdapter1 extends ArrayAdapter<String> {  // --CloneChangeRequired
    private ArrayList<String> mList;  // --CloneChangeRequired
    public ListAdapter1(Context context, int textViewResourceId,ArrayList<String> list) { // --CloneChangeRequired
        super(context, textViewResourceId, list);
        this.mList = list;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        View view = convertView;
        try{
        if (view == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.custom_radio, null);     // --CloneChangeRequired(list_item)
        }
        final String listItem = mList.get(position);    // --CloneChangeRequired
        if (listItem != null) {
            ( (TextView) view.findViewById(R.id.textView111) ).setText(listItem);
        }}catch(Exception e){

        }
        return view;
    }
}
</code>```

}

答:
Try now :

```<code>public class Forfattere extends Activity {
/** Called when the activity is first created. */
ArrayList<String> aList = new ArrayList<String>();
ListAdapter1 la = null;
ListView fList = null;
@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.forfattere);
    fList = (ListView)findViewById(R.id.Author_list);
    ArrayList<String> a = DBlistbookfestival.getAuthorName();
    for(int i=0;i<a.size();i++){
        aList.add(a.get(i));
        Log.v("all_data",a.get(i));
    }
    la = new ListAdapter1(this,android.R.layout.simple_list_item_1, aList);
    fList.setAdapter(la);
 }

private class ListAdapter1 extends ArrayAdapter<String> {  // --CloneChangeRequired
    private ArrayList<String> mList;  // --CloneChangeRequired
    public ListAdapter1(Context context, int textViewResourceId,ArrayList<String> list) { // --CloneChangeRequired
        super(context, textViewResourceId, list);
        this.mList = list;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        View view = convertView;
        try{
        if (view == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.custom_radio, null);     // --CloneChangeRequired(list_item)
        }
        final String listItem = mList.get(position);    // --CloneChangeRequired
        if (listItem != null) {
            ( (TextView) view.findViewById(R.id.textView111) ).setText(listItem);
        }}catch(Exception e){

        }
        return view;
    }
}
}
</code>```

In the following I used android default list item as you didn't declare one.

```<code>la = new ListAdapter1(this,android.R.layout.simple_list_item_1, aList);
</code>```

Title: Null pointer exeception in ListAdapter

Body:
I want to display Data in List View but I got Error Null Pointer Exception run time in line

fList.setAdapter(la);

My code is here List is complete printing in Log
Thanks

public class Forfattere extends Activity {
/** Called when the activity is first created. */
ArrayList<String> aList = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.forfattere);
    ListView fList = (ListView)findViewById(R.id.Author_list);
    ArrayList<String> a = DBlistbookfestival.getAuthorName();
    for(int i=0;i<a.size();i++){
        aList.add(a.get(i));
        Log.v("all_data",a.get(i));
    }
    ListAdapter1 la = new ListAdapter1(this, R.id.Author_list, aList);
    fList.setAdapter(la);
 }

private class ListAdapter1 extends ArrayAdapter<String> {  // --CloneChangeRequired
    private ArrayList<String> mList;  // --CloneChangeRequired
    public ListAdapter1(Context context, int textViewResourceId,ArrayList<String> list) { // --CloneChangeRequired
        super(context, textViewResourceId, list);
        this.mList = list;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        View view = convertView;
        try{
        if (view == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.custom_radio, null);     // --CloneChangeRequired(list_item)
        }
        final String listItem = mList.get(position);    // --CloneChangeRequired
        if (listItem != null) {
            ( (TextView) view.findViewById(R.id.textView111) ).setText(listItem);
        }}catch(Exception e){

        }
        return view;
    }
}

}

Body:
Try now :

public class Forfattere extends Activity {
/** Called when the activity is first created. */
ArrayList<String> aList = new ArrayList<String>();
ListAdapter1 la = null;
ListView fList = null;
@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.forfattere);
    fList = (ListView)findViewById(R.id.Author_list);
    ArrayList<String> a = DBlistbookfestival.getAuthorName();
    for(int i=0;i<a.size();i++){
        aList.add(a.get(i));
        Log.v("all_data",a.get(i));
    }
    la = new ListAdapter1(this,android.R.layout.simple_list_item_1, aList);
    fList.setAdapter(la);
 }

private class ListAdapter1 extends ArrayAdapter<String> {  // --CloneChangeRequired
    private ArrayList<String> mList;  // --CloneChangeRequired
    public ListAdapter1(Context context, int textViewResourceId,ArrayList<String> list) { // --CloneChangeRequired
        super(context, textViewResourceId, list);
        this.mList = list;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        View view = convertView;
        try{
        if (view == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.custom_radio, null);     // --CloneChangeRequired(list_item)
        }
        final String listItem = mList.get(position);    // --CloneChangeRequired
        if (listItem != null) {
            ( (TextView) view.findViewById(R.id.textView111) ).setText(listItem);
        }}catch(Exception e){

        }
        return view;
    }
}
}

In the following I used android default list item as you didn't declare one.

la = new ListAdapter1(this,android.R.layout.simple_list_item_1, aList);


问:
How to use actions or do scroll in app in Java?
TouchAction is deprecated.
Any pointers for new usage to do vertical Scroll?
Below code used. But not working as TouchAction is deprecated.</p>
```<code>Dimension dimension =driver.manage().window().getSize();
int start_x=(int) (dimension.width*0.5);
int start_y=(int) (dimension.height*0.9);
int end_x=(int) (dimension.width*0.2);
int end_y=(int) (dimension.height*0.1);
TouchAction touch =new TouchAction(driver);
touch.press(PointOption.point(start_x,start_y))
   .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)))
   .moveTo(PointOption.point(end_x, end_y))
   .release()
   .perform();
Thread.sleep(3000);
dimension =driver.manage().window().getSize();
start_x=(int) (dimension.width*0.2);
start_y=(int) (dimension.height*0.2);
end_x=(int) (dimension.width*0.5);
end_y=(int) (dimension.height*0.8);
touch =new TouchAction(driver);
touch.press(PointOption.point(start_x,start_y))
    .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)))
    .moveTo(PointOption.point(end_x, end_y))
    .release()
    .perform();
</code>```

答:
In Selenium 4/Appium 8 TouchActions replaced with W3C actions.

http://appium.io/docs/en/commands/interactions/actions/

For your example:

W3cActions Util Class

import org.openqa.selenium.Point
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import static java.time.Duration.ofMillis
import static org.openqa.selenium.interactions.PointerInput.Kind.TOUCH
import static org.openqa.selenium.interactions.PointerInput.MouseButton.LEFT
import static org.openqa.selenium.interactions.PointerInput.Origin.viewport

public class W3cActions {

    private final static PointerInput FINGER = new PointerInput(TOUCH, 'finger');

    public static void doSwipe(AppiumDriver driver, Point start, Point end, int duration) {
        Sequence swipe = new Sequence(FINGER, 1)
                .addAction(FINGER.createPointerMove(ofMillis(0), viewport(), start.getX(), start.getY()))
                .addAction(FINGER.createPointerDown(LEFT.asArg()))
                .addAction(FINGER.createPointerMove(ofMillis(duration), viewport(), end.getX(), end.getY()))
                .addAction(FINGER.createPointerUp(LEFT.asArg()));
        driver.perform(Arrays.asList(swipe));
    }

    public static void doTap(AppiumDriver driver, Point point, int duration) {
        Sequence tap = new Sequence(FINGER, 1)
                .addAction(FINGER.createPointerMove(ofMillis(0), viewport(), point.getX(), point.getY()))
                .addAction(FINGER.createPointerDown(LEFT.asArg()))
                .addAction(new Pause(FINGER, ofMillis(duration)))
                .addAction(FINGER.createPointerUp(LEFT.asArg()));
        driver.perform(Arrays.asList(tap));
    }

}
```
<p><strong>Swipe</strong></p>
<pre class="lang-java prettyprint-override"><code>Dimension dimension = driver.manage().window().getSize();
Point start = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.9));
Point end = new Point((int)(dimension.width*0.2), (int)(dimension.height*0.1));
W3cActions.doSwipe(driver, start, end, 1000);  //with duration 1s

Thread.sleep(3000);

start = new Point((int)(dimension.width*0.2), (int)(dimension.height*0.2));
end = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.8));
W3cActions.doSwipe(driver, start, end, 1000); //with duration 1s
</code>```

Tap

Dimension dimension = driver.manage().window().getSize();
Point forTap = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.9));
W3cActions.doTap(driver, forTap, 200); //with duration 200ms
```

Body:
TouchAction is deprecated.
Any pointers for new usage to do vertical Scroll?
Below code used. But not working as TouchAction is deprecated.

Dimension dimension =driver.manage().window().getSize();
int start_x=(int) (dimension.width*0.5);
int start_y=(int) (dimension.height*0.9);
int end_x=(int) (dimension.width*0.2);
int end_y=(int) (dimension.height*0.1);
TouchAction touch =new TouchAction(driver);
touch.press(PointOption.point(start_x,start_y))
   .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)))
   .moveTo(PointOption.point(end_x, end_y))
   .release()
   .perform();
Thread.sleep(3000);
dimension =driver.manage().window().getSize();
start_x=(int) (dimension.width*0.2);
start_y=(int) (dimension.height*0.2);
end_x=(int) (dimension.width*0.5);
end_y=(int) (dimension.height*0.8);
touch =new TouchAction(driver);
touch.press(PointOption.point(start_x,start_y))
    .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)))
    .moveTo(PointOption.point(end_x, end_y))
    .release()
    .perform();

Body:
In Selenium 4/Appium 8 TouchActions replaced with W3C actions.

http://appium.io/docs/en/commands/interactions/actions/

For your example:

W3cActions Util Class

import org.openqa.selenium.Point
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import static java.time.Duration.ofMillis
import static org.openqa.selenium.interactions.PointerInput.Kind.TOUCH
import static org.openqa.selenium.interactions.PointerInput.MouseButton.LEFT
import static org.openqa.selenium.interactions.PointerInput.Origin.viewport

public class W3cActions {

    private final static PointerInput FINGER = new PointerInput(TOUCH, 'finger');

    public static void doSwipe(AppiumDriver driver, Point start, Point end, int duration) {
        Sequence swipe = new Sequence(FINGER, 1)
                .addAction(FINGER.createPointerMove(ofMillis(0), viewport(), start.getX(), start.getY()))
                .addAction(FINGER.createPointerDown(LEFT.asArg()))
                .addAction(FINGER.createPointerMove(ofMillis(duration), viewport(), end.getX(), end.getY()))
                .addAction(FINGER.createPointerUp(LEFT.asArg()));
        driver.perform(Arrays.asList(swipe));
    }

    public static void doTap(AppiumDriver driver, Point point, int duration) {
        Sequence tap = new Sequence(FINGER, 1)
                .addAction(FINGER.createPointerMove(ofMillis(0), viewport(), point.getX(), point.getY()))
                .addAction(FINGER.createPointerDown(LEFT.asArg()))
                .addAction(new Pause(FINGER, ofMillis(duration)))
                .addAction(FINGER.createPointerUp(LEFT.asArg()));
        driver.perform(Arrays.asList(tap));
    }

}

Swipe

Dimension dimension = driver.manage().window().getSize();
Point start = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.9));
Point end = new Point((int)(dimension.width*0.2), (int)(dimension.height*0.1));
W3cActions.doSwipe(driver, start, end, 1000);  //with duration 1s

Thread.sleep(3000);

start = new Point((int)(dimension.width*0.2), (int)(dimension.height*0.2));
end = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.8));
W3cActions.doSwipe(driver, start, end, 1000); //with duration 1s

Tap

Dimension dimension = driver.manage().window().getSize();
Point forTap = new Point((int)(dimension.width*0.5), (int)(dimension.height*0.9));
W3cActions.doTap(driver, forTap, 200); //with duration 200ms


问:
how to register a callback function into shared library
my shared library (search.so) implements below interface as below

ILibrary.h

```<code>class ILibrary
{
   virtual void registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>& myinfo)>) = 0;
   virtual void startSearch() = 0;
};
</code>```

Library.h

```<code>class Library: public ILibrary {
public:
   void registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>& myinfo)>);
   void startSearch();
private:
   std::function<void(const std::shared_ptr<Info::info>& myinfo)> callback;
   //other members and functions here
}
</code>```

Library.cpp

```<code>Library::registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>&  myInfo)> cb)
{
   callback = cb;
}
</code>```

This is how I load the library and calls my functions from main.
how to register SearchResult function by calling registerSearchResultCallback here ?
I am not sure how to use dlsymb calls for this and wrap into the wrapper class which written below. I prefer to write dlsymb calls inside the already written below Wrapper class

main.cpp

```<code>void SearchResult(const std::shared_ptr<Info::info>& myinfo)> info)
{
     //using info for further operation
}

void main()
{
    std::shared_ptr<Wrapper<ILibrary>> loader = std::make_shared<Wrapper<ILibrary>>("search.so");
    loader->OpenLib();
    std::shared_ptr<ILibrary> iLib= loader->Instance();

    //how to call my library's 'registerSearchResultCallback'
    //to register 'SearchResult' function here ? Do we need to use 'dlSymb' calls
    //for this and if so how to write it in Wrapper class(below)

    //after that I call search function as below
    iLib->startSearch();
}
</code>```

I have a already written wrapper class to wrap the dl calls as below

```<code>class Wrapper : public IWrapper<T>
    {
    private:
        void            *_handle;
        std::string     _pathToLib;
        std::string     _allocClassSymbol;
        std::string     _deleteClassSymbol;

    public:

        Wrapper (std::string const &pathToLib,
            std::string const &allocClassSymbol = "allocator",
            std::string const &deleteClassSymbol = "deleter") :
            _handle(nullptr), _pathToLib(pathToLib),
            _allocClassSymbol(allocClassSymbol), _deleteClassSymbol(deleteClassSymbol)
        {
        }

        ~Wrapper () = default;

        void OpenLib() override
        {
            if (!(_handle = dlopen(_pathToLib.c_str(), RTLD_NOW | RTLD_LAZY))) {
                std::cerr << dlerror() << std::endl;
            }
        }

        std::shared_ptr<T> Instance() override
        {
            using allocClass = T *(*)();
            using deleteClass = void (*)(T *);

            auto allocFunc = reinterpret_cast<allocClass>(
                    dlsym(_handle, _allocClassSymbol.c_str()));
            auto deleteFunc = reinterpret_cast<deleteClass>(
                    dlsym(_handle, _deleteClassSymbol.c_str()));

            if (!allocFunc || !deleteFunc) {
                DLCloseLib();
                std::cerr << dlerror() << std::endl;
            }

            return std::shared_ptr<T>(
                    allocFunc(),
                    [deleteFunc](T *p){ deleteFunc(p); });
        }

        void CloseLib() override
        {
            if (dlclose(_handle) != 0) {
                std::cerr << dlerror() << std::endl;
            }
        }
    };
</code>```

答:
how to call my library's 'registerSearchResultCallback' to register 'SearchResult' function here ?

If SearchResult is a standalone function, it should be simply:

```<code>iLib->registerSearchResultCallback(SearchResult);
</code>```

If SearchResult() (and main()) is a non-static class method, it would need to look more this instead:

```<code>iLib->registerSearchResultCallback(
    [this](const std::shared_ptr<Info::info>& myinfo)> info){
        this->SearchResult(info);
    }
);
</code>```

Body:
my shared library (search.so) implements below interface as below

ILibrary.h

class ILibrary
{
   virtual void registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>& myinfo)>) = 0;
   virtual void startSearch() = 0;
};

Library.h

class Library: public ILibrary {
public:
   void registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>& myinfo)>);
   void startSearch();
private:
   std::function<void(const std::shared_ptr<Info::info>& myinfo)> callback;
   //other members and functions here
}

Library.cpp

Library::registerSearchResultCallback(std::function<void(const std::shared_ptr<Info::info>&  myInfo)> cb)
{
   callback = cb;
}

This is how I load the library and calls my functions from main.
how to register SearchResult function by calling registerSearchResultCallback here ?
I am not sure how to use dlsymb calls for this and wrap into the wrapper class which written below. I prefer to write dlsymb calls inside the already written below Wrapper class

main.cpp

void SearchResult(const std::shared_ptr<Info::info>& myinfo)> info)
{
     //using info for further operation
}

void main()
{
    std::shared_ptr<Wrapper<ILibrary>> loader = std::make_shared<Wrapper<ILibrary>>("search.so");
    loader->OpenLib();
    std::shared_ptr<ILibrary> iLib= loader->Instance();

    //how to call my library's 'registerSearchResultCallback'
    //to register 'SearchResult' function here ? Do we need to use 'dlSymb' calls
    //for this and if so how to write it in Wrapper class(below)

    //after that I call search function as below
    iLib->startSearch();
}

I have a already written wrapper class to wrap the dl calls as below

class Wrapper : public IWrapper<T>
    {
    private:
        void            *_handle;
        std::string     _pathToLib;
        std::string     _allocClassSymbol;
        std::string     _deleteClassSymbol;

    public:

        Wrapper (std::string const &pathToLib,
            std::string const &allocClassSymbol = "allocator",
            std::string const &deleteClassSymbol = "deleter") :
            _handle(nullptr), _pathToLib(pathToLib),
            _allocClassSymbol(allocClassSymbol), _deleteClassSymbol(deleteClassSymbol)
        {
        }

        ~Wrapper () = default;

        void OpenLib() override
        {
            if (!(_handle = dlopen(_pathToLib.c_str(), RTLD_NOW | RTLD_LAZY))) {
                std::cerr << dlerror() << std::endl;
            }
        }

        std::shared_ptr<T> Instance() override
        {
            using allocClass = T *(*)();
            using deleteClass = void (*)(T *);

            auto allocFunc = reinterpret_cast<allocClass>(
                    dlsym(_handle, _allocClassSymbol.c_str()));
            auto deleteFunc = reinterpret_cast<deleteClass>(
                    dlsym(_handle, _deleteClassSymbol.c_str()));

            if (!allocFunc || !deleteFunc) {
                DLCloseLib();
                std::cerr << dlerror() << std::endl;
            }

            return std::shared_ptr<T>(
                    allocFunc(),
                    [deleteFunc](T *p){ deleteFunc(p); });
        }

        void CloseLib() override
        {
            if (dlclose(_handle) != 0) {
                std::cerr << dlerror() << std::endl;
            }
        }
    };

Body:
how to call my library's 'registerSearchResultCallback' to register 'SearchResult' function here ?

If SearchResult is a standalone function, it should be simply:

iLib->registerSearchResultCallback(SearchResult);

If SearchResult() (and main()) is a non-static class method, it would need to look more this instead:

iLib->registerSearchResultCallback(
    [this](const std::shared_ptr<Info::info>& myinfo)> info){
        this->SearchResult(info);
    }
);


问:
Infinte loop in UseEffect retrieval from Firestore
I am trying to retrieve the document of the organization that is logged in after we see that Firebase Auth has the correct user uid. However, I'm getting an infinite loop in the useEffect function for that retrieval.

```<code>import { createContext, useEffect, useReducer} from 'react'
import { projectAuth, projectFirestore } from '../firebase'

export const AuthContext = createContext()

export const authReducer = (state, action) => {
    switch (action.type) {
        case 'LOGIN':
            return { ...state, user: action.payload }
        case 'LOGOUT':
            return { ...state, user: null }
        case 'AUTH_IS_READY':
            return { ...state, user: action.payload, authIsReady: true}
        case 'RETRIVED_ORG':
            return { ...state, org: action.payload }
        default:
            return state
    }
}

export const AuthContextProvider = ({ children }) => {
    const [state, dispatch] = useReducer(authReducer, {
        user: null,
        org: null,
        authIsReady: false
    })

    useEffect(() => {
        const unsub = projectAuth.onAuthStateChanged((user) => {
            dispatch({ type: 'AUTH_IS_READY', payload: user})
            unsub()
        })
    }, [])
    console.log('AuthContext state:', state)

    useEffect(() => {
        if (state.authIsReady) {
            projectFirestore.collection('orgs').doc(state.user.uid).get()
            .then(snapshot => {
                dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()})
            })
        }
    }, [state])

    return (
        <AuthContext.Provider value={{ ...state, dispatch }}>
            {children}
        </AuthContext.Provider>
    )
}
</code>```

This is the Context for Auth. As you can see, the first useEffect is run once and when it is complete, it triggers dispatch and sets the user and 'authIsReady' state to true from the reducer.

For the second useEffect, I want to run it when the authIsReady state is true because only then, I will know I have the user.uid. This does fire and uses the dispatch and sets the org but it is running multiple times. I think this is because I am including [state] in the second parameter, but if I remove it, I get an error message:
"React Hook useEffect has missing dependencies: 'state.authIsReady' and 'state.user.uid'. Either include them or remove the dependency array".

Is there a more elegant way of doing this?

答:
Your 2nd useEffect needs to depend just on state.authIsReady and state.user.uid. Right now its triggered in every state update, and when you do dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()}) you update the state, and it triggers 2nd useEffect again, fetches again, updates again and this is what is creating the infinite loop.

It should be:

```<code> useEffect(() => {
        if (state.authIsReady) {
            projectFirestore.collection('orgs').doc(state.user.uid).get()
            .then(snapshot => {
                dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()})
            })
        }
    }, [state.authIsReady, state.user.uid])
</code>```

Body:
I am trying to retrieve the document of the organization that is logged in after we see that Firebase Auth has the correct user uid. However, I'm getting an infinite loop in the useEffect function for that retrieval.

import { createContext, useEffect, useReducer} from 'react'
import { projectAuth, projectFirestore } from '../firebase'

export const AuthContext = createContext()

export const authReducer = (state, action) => {
    switch (action.type) {
        case 'LOGIN':
            return { ...state, user: action.payload }
        case 'LOGOUT':
            return { ...state, user: null }
        case 'AUTH_IS_READY':
            return { ...state, user: action.payload, authIsReady: true}
        case 'RETRIVED_ORG':
            return { ...state, org: action.payload }
        default:
            return state
    }
}

export const AuthContextProvider = ({ children }) => {
    const [state, dispatch] = useReducer(authReducer, {
        user: null,
        org: null,
        authIsReady: false
    })

    useEffect(() => {
        const unsub = projectAuth.onAuthStateChanged((user) => {
            dispatch({ type: 'AUTH_IS_READY', payload: user})
            unsub()
        })
    }, [])
    console.log('AuthContext state:', state)

    useEffect(() => {
        if (state.authIsReady) {
            projectFirestore.collection('orgs').doc(state.user.uid).get()
            .then(snapshot => {
                dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()})
            })
        }
    }, [state])

    return (
        <AuthContext.Provider value={{ ...state, dispatch }}>
            {children}
        </AuthContext.Provider>
    )
}

This is the Context for Auth. As you can see, the first useEffect is run once and when it is complete, it triggers dispatch and sets the user and 'authIsReady' state to true from the reducer.

For the second useEffect, I want to run it when the authIsReady state is true because only then, I will know I have the user.uid. This does fire and uses the dispatch and sets the org but it is running multiple times. I think this is because I am including [state] in the second parameter, but if I remove it, I get an error message:
"React Hook useEffect has missing dependencies: 'state.authIsReady' and 'state.user.uid'. Either include them or remove the dependency array".

Is there a more elegant way of doing this?

Body:
Your 2nd useEffect needs to depend just on state.authIsReady and state.user.uid. Right now its triggered in every state update, and when you do dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()}) you update the state, and it triggers 2nd useEffect again, fetches again, updates again and this is what is creating the infinite loop.

It should be:

 useEffect(() => {
        if (state.authIsReady) {
            projectFirestore.collection('orgs').doc(state.user.uid).get()
            .then(snapshot => {
                dispatch({ type: 'RETRIVED_ORG', payload: snapshot.data()})
            })
        }
    }, [state.authIsReady, state.user.uid])


问:
How to count emails in subfolders of a shared mailbox?
I want to count the number of emails in seven subfolders of a shared mailbox.

I also want the date of the last email in these folders.

The shared mailbox looks like

```<code>>"Shared Mailbox Name"
>>Inbox
>>>Folder one
>>>>A
>>>>B
>>>>C
>>>Folder two
>>>>D
>>>>E
>>>>F
>>>>G
</code>```

I want the result to show number of emails of all these folders together and not one by one. A, B, C, D, E, F, G.

I managed to get the number of emails for one folder at a time.

```<code>
Type TmyCount
    item As Date
    count As Integer
End Type

Sub Steuerung()

    Dim objNS As Outlook.NameSpace
    Dim objFolder As Outlook.MAPIFolder
    Set objNS = GetNamespace("MAPI")
   Set objFolder = objNS.Folders("shared mailbox name") 'folders of your current account

    'Creates a new Excel workbook
    Dim oXL As Object
    Set oXL = CreateObject("Excel.Application")
    Set oWB = oXL.Workbooks.Add
    oWB.sheets(1).Cells(2, 1).Value = "Date/Day"

    'Creates a list to which folders to be counted can be appended
    Dim colList As Collection
    Set colList = New Collection

    Set objFolder = objFolder.Folders("Inbox")
    Set objFolder = objFolder.Folders("Folder one")
    Set objFolder = objFolder.Folders("A")
    'Set objFolder = objFolder.Folders("B")

    'Adds all subfolders of 'Inbound chargeback processing' to the list
    Dim subF As Outlook.MAPIFolder
    For Each subF In objFolder.Folders
        colList.Add subF
    Next subF

     'SampleCode to add new folders to the edit list
     Set objFolder = objNS.Folders("shared mailbox name") ' folders of your current account
     Set objFolder = objFolder.Folders("Inbox")
     Set objFolder = objFolder.Folders("A")
     'Set objFolder = objFolder.Folders("B")
     colList.Add objFolder

    '-----------------------------------------------------------------------------------------------------------------
    'Please enter folders to be processed above this line

    'Iterates over the folder list and counts all mails and enters the values in the Excel workbook
    Dim k As Integer
    For k = 1 To colList.count
        Call Arrayfüllen(colList.item(k), k)
    Next k

    oWB.sheets(1).Cells(2, 2 * k).Value = "ReklaSumme"
    oWB.sheets(1).Cells(2, 2 * k + 1).Value = "ScanSumme"

    Dim n As Integer
    n = 3

    Dim countRekla As Integer

    Dim countScan As Integer

    While oWB.sheets(1).Cells(n, 1) <> ""
        countScan = 0
        countRekla = 0

        For m = 2 To 2 * k - 2

            If m Mod 2 = 1 Then

                countScan = countScan + oWB.sheets(1).Cells(n, m).Value

            Else

                countRekla = countRekla + oWB.sheets(1).Cells(n, m).Value

            End If

        Next m

        oWB.sheets(1).Cells(n, 2 * k).Value = CStr(countRekla)
        oWB.sheets(1).Cells(n, 2 * k + 1).Value = CStr(countScan)

        n = n + 1
    Wend

    'Makes the Excel workbooks visible
    oXL.Visible = True

End Sub

Sub Arrayfüllen(objFolder As Outlook.MAPIFolder, position As Integer)
    'Fills the objFolder folder's messages into two different arrays depending on the sender

    Dim Message As Object

    Dim arraysizeRekla As Integer
    arraysizeRekla = 0
    Dim arraysizeScan As Integer
    arraysizeScan = 0

    Dim msgInhaltRekla() As String
    Dim msgInhaltScan() As String

    For Each Message In objFolder.Items
        'Iterates over all items in the folder
        If Message.Class = 43 Then
            'If the message is from then
            If Message.SenderName = "Jonas, Adamski" Then
                'If it is a sender, fill the date in the msgContentScan array
                ReDim Preserve msgInhaltScan(arraysizeScan)
                msgInhaltScan(arraysizeScan) = Format(Message.ReceivedTime, "dd.mm.yyyy")
                arraysizeScan = arraysizeScan + 1

            Else
                'Otherwise, fill the date in the msgContentRekla array
                ReDim Preserve msgInhaltRekla(arraysizeRekla)
                msgInhaltRekla(arraysizeRekla) = Format(Message.ReceivedTime, "dd.mm.yyyy")
                arraysizeRekla = arraysizeRekla + 1

            End If

        Else
            'Falls es sich um ein Terminobjekt etc. handelt
        End If
    Next

    Dim reklaErgebnis() As TmyCount
    reklaErgebnis = ArrayVerarbeiten(msgInhaltRekla)
    'reklaEregbnis is filled with the aggregated result from msg InhaltRekla
    Dim scanErgebnis() As TmyCount
    scanErgebnis = ArrayVerarbeiten(msgInhaltScan)
    'scanResult is filled with the aggregated result from msgContentScan

    'Creates the heading in the Excel document
    oWB.sheets(1).Cells(1, 2 * position).Value = objFolder.Name
    oWB.sheets(1).Cells(2, 2 * position).Value = "Rekla"
    oWB.sheets(1).Cells(2, 2 * position + 1).Value = "Scan"

    Dim j As Integer

    If IsArrayEmpty(reklaErgebnis) = False Then
        'If array reklaResult is not empty

        For i = 0 To UBound(reklaErgebnis)
            'Go through the whole array

            j = 3
            While oWB.sheets(1).Cells(j, 1).Value <> reklaErgebnis(i).item And oWB.sheets(1).Cells(j, 1).Value <> vbNullString
                'Find suitable date or navigate to the end
                j = j + 1
            Wend

            If oWB.sheets(1).Cells(j, 1).Value <> reklaErgebnis(i).item Then
                'Empty line at the end
                oWB.sheets(1).Cells(j, 1).Value = reklaErgebnis(i).item
                oWB.sheets(1).Cells(j, 2 * position).Value = reklaErgebnis(i).count

            Else
                'Date line found
                oWB.sheets(1).Cells(j, 2 * position).Value = reklaErgebnis(i).count
            End If

        Next

    End If

    If IsArrayEmpty(scanErgebnis) = False Then
        'If Array scanResult is not empty

        For i = 0 To UBound(scanErgebnis)

            j = 3
            While oWB.sheets(1).Cells(j, 1).Value <> scanErgebnis(i).item And oWB.sheets(1).Cells(j, 1).Value <> vbNullString
                'Find suitable date or navigate to the end
                j = j + 1
            Wend

            If oWB.sheets(1).Cells(j, 1).Value <> scanErgebnis(i).item Then
                'Empty line at the end
                oWB.sheets(1).Cells(j, 1).Value = scanErgebnis(i).item
                oWB.sheets(1).Cells(j, 2 * position + 1).Value = scanErgebnis(i).count

            Else
                'Date line found
                oWB.sheets(1).Cells(j, 2 * position + 1).Value = scanErgebnis(i).count
            End If

        Next

    End If

End Sub
Function ArrayVerarbeiten(ByRef msgInhalt() As String) As TmyCount()
    'Aggregates msgContent by the dates, counting the occurrences

    Dim icount As Integer
    Dim acount() As TmyCount
    Dim i As Integer, index As Integer

    If IsStringArrayEmpty(msgInhalt) Then
        'If msgContent is not initialized, an uninitialized item is returned
        ArrayVerarbeiten = acount
        Exit Function
    End If

    icount = -1
    For i = 0 To UBound(msgInhalt)
        index = IsInArray(icount, acount, msgInhalt(i))
        If index < 0 Then
            icount = icount + 1
            ReDim Preserve acount(icount)
            acount(icount).item = msgInhalt(i)
            acount(icount).count = 1
        Else
            acount(index).count = acount(index).count + 1
        End If
    Next

    ArrayVerarbeiten = acount

End Function

Function IsInArray(icount As Integer, acount() As TmyCount, ele As String) As Integer
    'Prüft, ob ele in account enthalten ist
    'Prüft nur die Elemente an den Stellen < icount

    Dim i As Integer
    IsInArray = -1
    For i = 0 To icount
        If acount(i).item = ele Then
            IsInArray = i
            Exit Function
        End If
    Next
End Function

Function IsArrayEmpty(anArray() As TmyCount) As Boolean
    'Checks whether a TmyCount array has not been initialized

    Dim i As Integer

    On Error Resume Next
        i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 9
            IsArrayEmpty = True
        Case Else
            IsArrayEmpty = False
    End Select
End Function

Function IsStringArrayEmpty(anArray() As String) As Boolean
    'Checks whether a string array is uninitialized

    Dim i As Integer

    On Error Resume Next
    i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 9
           IsStringArrayEmpty = True
        Case Else
            IsStringArrayEmpty = False
    End Select
End Function```

**And this is the code to iterate over all folder recursively.**

    Private Sub processFolder(ByVal oParent As Outlook.MAPIFolder)

        Dim oFolder As Outlook.MAPIFolder
        Dim oMail As Outlook.MailItem

        Debug.Print(oParent.Items.Count)

        For Each oMail In oParent.Items

        'Get your data here ...

        Next

        If (oParent.Folders.Count > 0) Then
            For Each oFolder In oParent.Folders
                processFolder oFolder
            Next
        End If
End Sub
```

答:
Firstly, lCurrentItemsCount parameter must be declared ByRef to make it an in/out parameter.

To get the date of the latest email, retrieve the Items collection from MAPIFolder.Items, call Items.Sort to sort of the ReceivedTime property, then call Items.GetFirst to get back the MailItem object. Use MailItem.ReceivedTime property.

Body:
I want to count the number of emails in seven subfolders of a shared mailbox.

I also want the date of the last email in these folders.

The shared mailbox looks like

>"Shared Mailbox Name"
>>Inbox
>>>Folder one
>>>>A
>>>>B
>>>>C
>>>Folder two
>>>>D
>>>>E
>>>>F
>>>>G

I want the result to show number of emails of all these folders together and not one by one. A, B, C, D, E, F, G.

I managed to get the number of emails for one folder at a time.

Type TmyCount
    item As Date
    count As Integer
End Type

Sub Steuerung()

    Dim objNS As Outlook.NameSpace
    Dim objFolder As Outlook.MAPIFolder
    Set objNS = GetNamespace("MAPI")
   Set objFolder = objNS.Folders("shared mailbox name") 'folders of your current account

    'Creates a new Excel workbook
    Dim oXL As Object
    Set oXL = CreateObject("Excel.Application")
    Set oWB = oXL.Workbooks.Add
    oWB.sheets(1).Cells(2, 1).Value = "Date/Day"

    'Creates a list to which folders to be counted can be appended
    Dim colList As Collection
    Set colList = New Collection

    Set objFolder = objFolder.Folders("Inbox")
    Set objFolder = objFolder.Folders("Folder one")
    Set objFolder = objFolder.Folders("A")
    'Set objFolder = objFolder.Folders("B")

    'Adds all subfolders of 'Inbound chargeback processing' to the list
    Dim subF As Outlook.MAPIFolder
    For Each subF In objFolder.Folders
        colList.Add subF
    Next subF

     'SampleCode to add new folders to the edit list
     Set objFolder = objNS.Folders("shared mailbox name") ' folders of your current account
     Set objFolder = objFolder.Folders("Inbox")
     Set objFolder = objFolder.Folders("A")
     'Set objFolder = objFolder.Folders("B")
     colList.Add objFolder

    '-----------------------------------------------------------------------------------------------------------------
    'Please enter folders to be processed above this line

    'Iterates over the folder list and counts all mails and enters the values in the Excel workbook
    Dim k As Integer
    For k = 1 To colList.count
        Call Arrayfüllen(colList.item(k), k)
    Next k

    oWB.sheets(1).Cells(2, 2 * k).Value = "ReklaSumme"
    oWB.sheets(1).Cells(2, 2 * k + 1).Value = "ScanSumme"

    Dim n As Integer
    n = 3

    Dim countRekla As Integer

    Dim countScan As Integer

    While oWB.sheets(1).Cells(n, 1) <> ""
        countScan = 0
        countRekla = 0

        For m = 2 To 2 * k - 2

            If m Mod 2 = 1 Then

                countScan = countScan + oWB.sheets(1).Cells(n, m).Value

            Else

                countRekla = countRekla + oWB.sheets(1).Cells(n, m).Value

            End If

        Next m

        oWB.sheets(1).Cells(n, 2 * k).Value = CStr(countRekla)
        oWB.sheets(1).Cells(n, 2 * k + 1).Value = CStr(countScan)

        n = n + 1
    Wend

    'Makes the Excel workbooks visible
    oXL.Visible = True

End Sub

Sub Arrayfüllen(objFolder As Outlook.MAPIFolder, position As Integer)
    'Fills the objFolder folder's messages into two different arrays depending on the sender

    Dim Message As Object

    Dim arraysizeRekla As Integer
    arraysizeRekla = 0
    Dim arraysizeScan As Integer
    arraysizeScan = 0

    Dim msgInhaltRekla() As String
    Dim msgInhaltScan() As String

    For Each Message In objFolder.Items
        'Iterates over all items in the folder
        If Message.Class = 43 Then
            'If the message is from then
            If Message.SenderName = "Jonas, Adamski" Then
                'If it is a sender, fill the date in the msgContentScan array
                ReDim Preserve msgInhaltScan(arraysizeScan)
                msgInhaltScan(arraysizeScan) = Format(Message.ReceivedTime, "dd.mm.yyyy")
                arraysizeScan = arraysizeScan + 1

            Else
                'Otherwise, fill the date in the msgContentRekla array
                ReDim Preserve msgInhaltRekla(arraysizeRekla)
                msgInhaltRekla(arraysizeRekla) = Format(Message.ReceivedTime, "dd.mm.yyyy")
                arraysizeRekla = arraysizeRekla + 1

            End If

        Else
            'Falls es sich um ein Terminobjekt etc. handelt
        End If
    Next

    Dim reklaErgebnis() As TmyCount
    reklaErgebnis = ArrayVerarbeiten(msgInhaltRekla)
    'reklaEregbnis is filled with the aggregated result from msg InhaltRekla
    Dim scanErgebnis() As TmyCount
    scanErgebnis = ArrayVerarbeiten(msgInhaltScan)
    'scanResult is filled with the aggregated result from msgContentScan

    'Creates the heading in the Excel document
    oWB.sheets(1).Cells(1, 2 * position).Value = objFolder.Name
    oWB.sheets(1).Cells(2, 2 * position).Value = "Rekla"
    oWB.sheets(1).Cells(2, 2 * position + 1).Value = "Scan"

    Dim j As Integer

    If IsArrayEmpty(reklaErgebnis) = False Then
        'If array reklaResult is not empty

        For i = 0 To UBound(reklaErgebnis)
            'Go through the whole array

            j = 3
            While oWB.sheets(1).Cells(j, 1).Value <> reklaErgebnis(i).item And oWB.sheets(1).Cells(j, 1).Value <> vbNullString
                'Find suitable date or navigate to the end
                j = j + 1
            Wend

            If oWB.sheets(1).Cells(j, 1).Value <> reklaErgebnis(i).item Then
                'Empty line at the end
                oWB.sheets(1).Cells(j, 1).Value = reklaErgebnis(i).item
                oWB.sheets(1).Cells(j, 2 * position).Value = reklaErgebnis(i).count

            Else
                'Date line found
                oWB.sheets(1).Cells(j, 2 * position).Value = reklaErgebnis(i).count
            End If

        Next

    End If

    If IsArrayEmpty(scanErgebnis) = False Then
        'If Array scanResult is not empty

        For i = 0 To UBound(scanErgebnis)

            j = 3
            While oWB.sheets(1).Cells(j, 1).Value <> scanErgebnis(i).item And oWB.sheets(1).Cells(j, 1).Value <> vbNullString
                'Find suitable date or navigate to the end
                j = j + 1
            Wend

            If oWB.sheets(1).Cells(j, 1).Value <> scanErgebnis(i).item Then
                'Empty line at the end
                oWB.sheets(1).Cells(j, 1).Value = scanErgebnis(i).item
                oWB.sheets(1).Cells(j, 2 * position + 1).Value = scanErgebnis(i).count

            Else
                'Date line found
                oWB.sheets(1).Cells(j, 2 * position + 1).Value = scanErgebnis(i).count
            End If

        Next

    End If

End Sub
Function ArrayVerarbeiten(ByRef msgInhalt() As String) As TmyCount()
    'Aggregates msgContent by the dates, counting the occurrences

    Dim icount As Integer
    Dim acount() As TmyCount
    Dim i As Integer, index As Integer

    If IsStringArrayEmpty(msgInhalt) Then
        'If msgContent is not initialized, an uninitialized item is returned
        ArrayVerarbeiten = acount
        Exit Function
    End If

    icount = -1
    For i = 0 To UBound(msgInhalt)
        index = IsInArray(icount, acount, msgInhalt(i))
        If index < 0 Then
            icount = icount + 1
            ReDim Preserve acount(icount)
            acount(icount).item = msgInhalt(i)
            acount(icount).count = 1
        Else
            acount(index).count = acount(index).count + 1
        End If
    Next

    ArrayVerarbeiten = acount

End Function

Function IsInArray(icount As Integer, acount() As TmyCount, ele As String) As Integer
    'Prüft, ob ele in account enthalten ist
    'Prüft nur die Elemente an den Stellen < icount

    Dim i As Integer
    IsInArray = -1
    For i = 0 To icount
        If acount(i).item = ele Then
            IsInArray = i
            Exit Function
        End If
    Next
End Function

Function IsArrayEmpty(anArray() As TmyCount) As Boolean
    'Checks whether a TmyCount array has not been initialized

    Dim i As Integer

    On Error Resume Next
        i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 9
            IsArrayEmpty = True
        Case Else
            IsArrayEmpty = False
    End Select
End Function

Function IsStringArrayEmpty(anArray() As String) As Boolean
    'Checks whether a string array is uninitialized

    Dim i As Integer

    On Error Resume Next
    i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 9
           IsStringArrayEmpty = True
        Case Else
            IsStringArrayEmpty = False
    End Select
End Function```

**And this is the code to iterate over all folder recursively.**

    Private Sub processFolder(ByVal oParent As Outlook.MAPIFolder)

        Dim oFolder As Outlook.MAPIFolder
        Dim oMail As Outlook.MailItem

        Debug.Print(oParent.Items.Count)

        For Each oMail In oParent.Items

        'Get your data here ...

        Next

        If (oParent.Folders.Count > 0) Then
            For Each oFolder In oParent.Folders
                processFolder oFolder
            Next
        End If
End Sub


问:
How to get cookiecutter to output to current working directory instead of nested directory?
We have a number of use cases where we'd like to be able to call cookiecutter and have the files and directories generated get put into the current working directory.

Simple example

What is essentially desired.

```<code>$ cd path/to/repo
$ ls
a.txt
$ cookiecutter path/to/template
$ls
a.txt b.txt
</code>```

What the result actually is

```<code>$ cd path/to/repo
$ ls
a.txt
$ cookiecutter path/to/template
$ls
a.txt
template/
  b.txt
</code>```

Things I've tried

You could imagine the template being something like this.

```<code>template/
  cookiecutter.json
  b.txt
</code>```

But cookiecutter appears to require there to be a template root by default to avoid cookiecutter.exceptions.NonTemplatedInputDirException.

So, add a directory to contain the template files and try and output it to a particular directory.

```<code>template/
  cookiecutter.json
  {{cookiecutter.name}}
</code>```

But then the template files are just nested in a subdirectory of the current working directory like shown above of course.

I also expect one could use a post-generate hook to move the template's output files to where you want, but that seems like a bit of a hack...

I keep seeing comments on GitHub saying basically "this is solved", but I can't seem to find documentation on how to use whatever feature was added to accommodate this use case.

https://github.com/cookiecutter/cookiecutter/issues/1068

https://github.com/cookiecutter/cookiecutter/issues/35

https://github.com/cookiecutter/cookiecutter/issues/153

答:
The issue is closed, but this doesn't mean it is solved.

The only way to do this is with post-generate hook moving the files out of your folder and deleting the folder.

If you are on a *NIX system, you can use the following simple script:

```<code>#!/bin/sh

mv * ..
rm -rfv ../{{ cookiecutter.project_name }}
</code>```

Where cookiecutter.project_name is your template folder.

Body:
We have a number of use cases where we'd like to be able to call cookiecutter and have the files and directories generated get put into the current working directory.

Simple example

What is essentially desired.

$ cd path/to/repo
$ ls
a.txt
$ cookiecutter path/to/template
$ls
a.txt b.txt

What the result actually is

$ cd path/to/repo
$ ls
a.txt
$ cookiecutter path/to/template
$ls
a.txt
template/
  b.txt

Things I've tried

You could imagine the template being something like this.

template/
  cookiecutter.json
  b.txt

But cookiecutter appears to require there to be a template root by default to avoid cookiecutter.exceptions.NonTemplatedInputDirException.

So, add a directory to contain the template files and try and output it to a particular directory.

template/
  cookiecutter.json
  {{cookiecutter.name}}

But then the template files are just nested in a subdirectory of the current working directory like shown above of course.

I also expect one could use a post-generate hook to move the template's output files to where you want, but that seems like a bit of a hack...

I keep seeing comments on GitHub saying basically "this is solved", but I can't seem to find documentation on how to use whatever feature was added to accommodate this use case.

https://github.com/cookiecutter/cookiecutter/issues/1068

https://github.com/cookiecutter/cookiecutter/issues/35

https://github.com/cookiecutter/cookiecutter/issues/153

Body:
The issue is closed, but this doesn't mean it is solved.

The only way to do this is with post-generate hook moving the files out of your folder and deleting the folder.

If you are on a *NIX system, you can use the following simple script:

#!/bin/sh

mv * ..
rm -rfv ../{{ cookiecutter.project_name }}

Where cookiecutter.project_name is your template folder.


问:
Why is this web scrape not working on python?
I haven’t recently been using the code attached. For the past few weeks, it has been working completely fine and always produced results. However, I used this today and for some reason it didn’t work. Could you please help and provide a solution to the problem.

```<code>import requests, json
from bs4 import BeautifulSoup

headers = {
    "User-Agent":
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
}

params = {"q": "dji", "hl": "en", 'gl': 'us', 'tbm': 'shop'}

response = requests.get("https://www.google.com/search",
                        params=params,
                        headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# list with two dict() combined
shopping_data = []
shopping_results_dict = {}

for shopping_result in soup.select('.sh-dgr__content'):
    title = shopping_result.select_one('.Lq5OHe.eaGTj h4').text
    product_link = f"https://www.google.com{shopping_result.select_one('.Lq5OHe.eaGTj')['href']}"
    source = shopping_result.select_one('.IuHnof').text
    price = shopping_result.select_one('span.kHxwFf span').text

    try:
        rating = shopping_result.select_one('.Rsc7Yb').text
    except:
        rating = None

    try:
        reviews = shopping_result.select_one('.Rsc7Yb').next_sibling.next_sibling
    except:
        reviews = None

    try:
        delivery = shopping_result.select_one('.vEjMR').text
    except:
        delivery = None

    shopping_results_dict.update({
        'shopping_results': [{
            'title': title,
            'link': product_link,
            'source': source,
            'price': price,
            'rating': rating,
            'reviews': reviews,
            'delivery': delivery,
        }]
    })

    shopping_data.append(dict(shopping_results_dict))

print(title)
</code>```

答:
Because .select in for shopping_result in soup.select('.sh-dgr__content'): could not find any element so it gives you an empty list. Therefor the body of the for-loop is not executed. Python jumps out of the loop.

title only exists and is defined when the body of the for loop executes.

You should make sure you used a correct method to find your element(s).

Body:
I haven’t recently been using the code attached. For the past few weeks, it has been working completely fine and always produced results. However, I used this today and for some reason it didn’t work. Could you please help and provide a solution to the problem.

import requests, json
from bs4 import BeautifulSoup

headers = {
    "User-Agent":
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
}

params = {"q": "dji", "hl": "en", 'gl': 'us', 'tbm': 'shop'}

response = requests.get("https://www.google.com/search",
                        params=params,
                        headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# list with two dict() combined
shopping_data = []
shopping_results_dict = {}

for shopping_result in soup.select('.sh-dgr__content'):
    title = shopping_result.select_one('.Lq5OHe.eaGTj h4').text
    product_link = f"https://www.google.com{shopping_result.select_one('.Lq5OHe.eaGTj')['href']}"
    source = shopping_result.select_one('.IuHnof').text
    price = shopping_result.select_one('span.kHxwFf span').text

    try:
        rating = shopping_result.select_one('.Rsc7Yb').text
    except:
        rating = None

    try:
        reviews = shopping_result.select_one('.Rsc7Yb').next_sibling.next_sibling
    except:
        reviews = None

    try:
        delivery = shopping_result.select_one('.vEjMR').text
    except:
        delivery = None

    shopping_results_dict.update({
        'shopping_results': [{
            'title': title,
            'link': product_link,
            'source': source,
            'price': price,
            'rating': rating,
            'reviews': reviews,
            'delivery': delivery,
        }]
    })

    shopping_data.append(dict(shopping_results_dict))

print(title)


问:
IOptions Injection
It seems to me that it's a bad idea to have a domain service require an instance of IOptions<T> to pass it configuration.   Now I've got to pull additional (unnecessary?) dependencies into the library.  I've seen lots of examples of injecting IOptions all over the web, but I fail to see the added benefit of it.

Why not just inject that actual POCO into the service?

```<code>    services.AddTransient<IConnectionResolver>(x =>
    {
        var appSettings = x.GetService<IOptions<AppSettings>>();

        return new ConnectionResolver(appSettings.Value);
    });
</code>```

Or even use this mechanism:

```<code>        AppSettings appSettings = new AppSettings();

        Configuration.GetSection("AppSettings").Bind(appSettings);

        services.AddTransient<IConnectionResolver>(x =>
        {
             return new ConnectionResolver(appSettings.SomeValue);
        });
</code>```

Usage of the settings:

```<code>public class MyConnectionResolver
{
     // Why this?
     public MyConnectionResolver(IOptions<AppSettings> appSettings)
     {
           ...
     }

     // Why not this?
     public MyConnectionResolver(AppSettings appSettings)
     {
           ...
     }

     // Or this
     public MyConnectionResolver(IAppSettings appSettings)
     {
           ...
     }
}
</code>```

Why the additional dependencies?  What does IOptions buy me instead of the old school way of injecting stuff?

答:
I would recommend avoiding it wherever possible. I used to really like IOptions back when I was working primarily with core but as soon as you're in a hybrid framework scenario it's enough to drive you spare.

I found a similar issue with ILogger - Code that should work across frameworks won't because I just can't get it to bind properly as the code is too dependent on the DI framework.

Title: IOptions Injection

Body:
It seems to me that it's a bad idea to have a domain service require an instance of IOptions<T> to pass it configuration.   Now I've got to pull additional (unnecessary?) dependencies into the library.  I've seen lots of examples of injecting IOptions all over the web, but I fail to see the added benefit of it.

Why not just inject that actual POCO into the service?

    services.AddTransient<IConnectionResolver>(x =>
    {
        var appSettings = x.GetService<IOptions<AppSettings>>();

        return new ConnectionResolver(appSettings.Value);
    });

Or even use this mechanism:

        AppSettings appSettings = new AppSettings();

        Configuration.GetSection("AppSettings").Bind(appSettings);

        services.AddTransient<IConnectionResolver>(x =>
        {
             return new ConnectionResolver(appSettings.SomeValue);
        });

Usage of the settings:

public class MyConnectionResolver
{
     // Why this?
     public MyConnectionResolver(IOptions<AppSettings> appSettings)
     {
           ...
     }

     // Why not this?
     public MyConnectionResolver(AppSettings appSettings)
     {
           ...
     }

     // Or this
     public MyConnectionResolver(IAppSettings appSettings)
     {
           ...
     }
}

Why the additional dependencies?  What does IOptions buy me instead of the old school way of injecting stuff?


问:
Integration tests work fine from flutter drive, but hang when entering text in Firebase Test Lab
I have the following sign-in test set up for my app:

testWidgets('sign in with email and password', (WidgetTester tester) async {
  app.main();
  await tester.pumpAndSettle(Duration(seconds: 3));
  final emailInputFinder = find.byKey(Key('type-email'));
  final passwordInputFinder = find.byKey(Key('type-password'));
  final emailButtonFinder = find.byKey(Key('enter-email'));
  final passwordButtonFinder = find.byKey(Key('enter-password'));
  final dashboardFinder = find.byKey(Key('dashboard'));
  await tester.enterText(emailInputFinder, 'test.lab.user.01@...');
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.tap(emailButtonFinder);
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.enterText(passwordInputFinder, '...');
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.tap(passwordButtonFinder);
  await tester.pumpAndSettle(Duration(seconds: 3));
  expect(dashboardFinder, findsOneWidget);
});
```
<p>The hardcoded 3 second delay isn't ideal, but without it I can't run the tests using the driver.</p>
<p>Running on my local machine with the driver is fine. I use the command</p>
```flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart
```

But when I upload the Espresso test to Firebase Test Lab and review the video, the sign-in screen loads up, but the first enterText() command seems to have no effect. Nothing is added to the text field, and the test just times out.

I have tried various combinations of tester.tap() and tester.showKeyboard(), but so far, nothing is coming up.

How can I get enterText() to work correctly in the Espresso environment supported by TestLab?

答:
Try calling binding.testTextInput.register():

```<code>  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;

// Necessary for being able to enterText when not in debug mode
  binding.testTextInput.register();
</code>```

There is an issue in the flutter repo about documenting this. Basically if you're not in  debug mode you have to call binding.testTextInput.register() in order for tester.enterText to work.

Body:
I have the following sign-in test set up for my app:

testWidgets('sign in with email and password', (WidgetTester tester) async {
  app.main();
  await tester.pumpAndSettle(Duration(seconds: 3));
  final emailInputFinder = find.byKey(Key('type-email'));
  final passwordInputFinder = find.byKey(Key('type-password'));
  final emailButtonFinder = find.byKey(Key('enter-email'));
  final passwordButtonFinder = find.byKey(Key('enter-password'));
  final dashboardFinder = find.byKey(Key('dashboard'));
  await tester.enterText(emailInputFinder, 'test.lab.user.01@...');
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.tap(emailButtonFinder);
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.enterText(passwordInputFinder, '...');
  await tester.pumpAndSettle(Duration(seconds: 3));
  await tester.tap(passwordButtonFinder);
  await tester.pumpAndSettle(Duration(seconds: 3));
  expect(dashboardFinder, findsOneWidget);
});

The hardcoded 3 second delay isn't ideal, but without it I can't run the tests using the driver.

Running on my local machine with the driver is fine. I use the command

flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart

But when I upload the Espresso test to Firebase Test Lab and review the video, the sign-in screen loads up, but the first enterText() command seems to have no effect. Nothing is added to the text field, and the test just times out.

I have tried various combinations of tester.tap() and tester.showKeyboard(), but so far, nothing is coming up.

How can I get enterText() to work correctly in the Espresso environment supported by TestLab?

Body:
Try calling binding.testTextInput.register():

  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;

// Necessary for being able to enterText when not in debug mode
  binding.testTextInput.register();

There is an issue in the flutter repo about documenting this. Basically if you're not in  debug mode you have to call binding.testTextInput.register() in order for tester.enterText to work.


问:
How can I authenticate users on a CMS for an iphone app?
I am working on an iPhone app which will fetch data (images + text) from a CMS. I had a look at the Wordpress CMS, but the app is subscription based. How should I go about authenticating the subscribers which are being directed to the cms?

Can anyone guide me?

Thanks

答:
Your question is a bit vague, and broad, perhaps if you broke it down a bit.

Are you using an iphone app, or a standard page with a Mobil browser?

If it's an standalone app are you having problems getting it to talk to your server/CMS?

You having problems authenticating https vs http?

If your having problems with your cms or are you after cms to start with?

From the sound of it Drupal could work well with the services module and probably Ubercart to handle the subscription. With zen (base theme) and some modifications** you can make it Mobil friendly.

http://drupal.org/start

http://drupal.org/project/services

http://drupal.org/project/ubercart

http://drupal.org/project/zen

** http://drupal.org/node/1008582


问:
Problem with filling the linked list with strtok
Im having troubles with the next piece of code...

I have defined a linked list struct

```<code>    typedef struct node {
        char *cmd;
        char *value;
        int delay;
        struct node *next;
    } node_t;
</code>```

im reading commands from a text file called commands.txt

```<code>write:0x02:1
read:0x04:2
set:0xff:2
reset:0xfa:2
</code>```

the code below works if i use two buffers (temp and temp1) but if i replace temp1 with temp it does not parse it correctly. it gives me

```<code>Tokenized2 read x04 1
Tokenized2 read 0x04 2
Tokenized2 read x04 1
Tokenized2 read 0x04 2
</code>```

The code is:

```<code>    char *filename = "commands.txt";
    FILE *fp = fopen(filename, "r");

    node_t *head = (node_t *)malloc(sizeof(node_t));
    node_t *hp = head;
    char temp[14];
    char temp1[14];

    fgets(temp, 14, fp);
    hp->cmd = strtok(temp, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = (node_t *)malloc(sizeof(node_t));
    hp = (node_t *)hp->next; Blaz

    fgets(temp1, 14, fp);
    hp->cmd = strtok(temp1, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = NULL;
    hp = head;

    printf("Tokenized2 %s %s %d\n", hp->cmd, hp->value, hp->delay);
    hp = hp->next;
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);
    printf("Tokenized2 %s %s %d\n", head->cmd, head->value, head->delay);
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);

    fclose(fp);
</code>```

The bottom printfs are redundant, I was just testing if it works with classic access to head and via pointer.
Eventually I would like to make this piece of code work.

```<code>    const unsigned MAX_LENGTH = 256;
    char cmdbuffer[MAX_LENGTH];
    node_t *head = (node_t *)malloc(sizeof(node_t));
    node_t *hp = head;
    while (fgets(cmdbuffer, MAX_LENGTH, fp)) {
        hp->cmd = strtok(cmdbuffer, ":");
        hp->value = strtok(0, ":");
        hp->delay = atoi(strtok(0, ":"));
        hp->next = (node_t *)malloc(sizeof(node_t));
        hp = (node_t *)hp->next;
    }
    hp->next = NULL;
    printf("Tokenized %s %s %d\n", head->cmd, head->value, head->delay);
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);
</code>```

How can I solve this problem?

答:
That's because of these lines:

hp->cmd = strtok(temp, ":");
hp->value = strtok(0, ":");
// ...

fgets(temp, 14, fp); // here temp1 was replaced with temp
```
<p>You are basically replacing the first and second <code>:</code> in <code>temp</code> with a terminator (<code>\0</code>) and then assigning <code>hp->cmd = temp;</code> and <code>hp->value = temp + some_offset;</code>.</p>
<p>Then, if you read into <code>temp</code> again, the old contents will be overwritten and the old assigned values will reference some bad unrelated offset in the new data in the buffer. Using two buffers fixes the issue because you are no longer overwriting the data of the first read with the second one.</p>
<p>If you only want to use one temporary buffer for reading then you will have to use <code>strdup()</code> to copy it somewhere else before using <code>strtok()</code> and assigning <code>->cmd</code> and <code>->value</code>, or just <code>malloc()</code> the buffer right away, so that each time you do these assignments they will refer to different newly allocated strings. If you do this, remember to also <code>free()</code> the allocated buffers later on.</p>
<hr />
<p>Something along the lines of this (check the code for yourself, I did not test it):</p>
<pre class="lang-c prettyprint-override"><code>const unsigned MAX_LENGTH = 256;
node_t *head = malloc(sizeof(node_t));
node_t *hp = head;
char *cmdbuffer;

head->next = NULL;

while (1) {
    cmdbuffer = malloc(MAX_LENGTH);
    if (fgets(cmdbuffer, MAX_LENGTH, fp)) {
        break;
    }

    hp->cmd = strtok(cmdbuffer, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = malloc(sizeof(node_t));
    hp = hp->next;
}

if (hp->next) {
    // careful here you need to free before assigning NULL
    // or you leak memory
    free(hp->next);
    hp->next = NULL;
}

// ...

node_t *tmp;
hp = head;

while (hp) {
    tmp = hp;
    hp = hp->next;
    free(tmp->cmd);
    free(tmp);
}
</code>```

Anyway, do not cast the return value of malloc().

Body:
Im having troubles with the next piece of code...

I have defined a linked list struct

    typedef struct node {
        char *cmd;
        char *value;
        int delay;
        struct node *next;
    } node_t;

im reading commands from a text file called commands.txt

write:0x02:1
read:0x04:2
set:0xff:2
reset:0xfa:2

the code below works if i use two buffers (temp and temp1) but if i replace temp1 with temp it does not parse it correctly. it gives me

Tokenized2 read x04 1
Tokenized2 read 0x04 2
Tokenized2 read x04 1
Tokenized2 read 0x04 2

The code is:

    char *filename = "commands.txt";
    FILE *fp = fopen(filename, "r");

    node_t *head = (node_t *)malloc(sizeof(node_t));
    node_t *hp = head;
    char temp[14];
    char temp1[14];

    fgets(temp, 14, fp);
    hp->cmd = strtok(temp, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = (node_t *)malloc(sizeof(node_t));
    hp = (node_t *)hp->next; Blaz

    fgets(temp1, 14, fp);
    hp->cmd = strtok(temp1, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = NULL;
    hp = head;

    printf("Tokenized2 %s %s %d\n", hp->cmd, hp->value, hp->delay);
    hp = hp->next;
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);
    printf("Tokenized2 %s %s %d\n", head->cmd, head->value, head->delay);
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);

    fclose(fp);

The bottom printfs are redundant, I was just testing if it works with classic access to head and via pointer.
Eventually I would like to make this piece of code work.

    const unsigned MAX_LENGTH = 256;
    char cmdbuffer[MAX_LENGTH];
    node_t *head = (node_t *)malloc(sizeof(node_t));
    node_t *hp = head;
    while (fgets(cmdbuffer, MAX_LENGTH, fp)) {
        hp->cmd = strtok(cmdbuffer, ":");
        hp->value = strtok(0, ":");
        hp->delay = atoi(strtok(0, ":"));
        hp->next = (node_t *)malloc(sizeof(node_t));
        hp = (node_t *)hp->next;
    }
    hp->next = NULL;
    printf("Tokenized %s %s %d\n", head->cmd, head->value, head->delay);
    printf("Tokenized2 %s %s %d\n", head->next->cmd, head->next->value, head->next->delay);

How can I solve this problem?

Body:
That's because of these lines:

hp->cmd = strtok(temp, ":");
hp->value = strtok(0, ":");
// ...

fgets(temp, 14, fp); // here temp1 was replaced with temp

You are basically replacing the first and second : in temp with a terminator (\0) and then assigning hp->cmd = temp; and hp->value = temp + some_offset;.

Then, if you read into temp again, the old contents will be overwritten and the old assigned values will reference some bad unrelated offset in the new data in the buffer. Using two buffers fixes the issue because you are no longer overwriting the data of the first read with the second one.

If you only want to use one temporary buffer for reading then you will have to use strdup() to copy it somewhere else before using strtok() and assigning ->cmd and ->value, or just malloc() the buffer right away, so that each time you do these assignments they will refer to different newly allocated strings. If you do this, remember to also free() the allocated buffers later on.

Something along the lines of this (check the code for yourself, I did not test it):

const unsigned MAX_LENGTH = 256;
node_t *head = malloc(sizeof(node_t));
node_t *hp = head;
char *cmdbuffer;

head->next = NULL;

while (1) {
    cmdbuffer = malloc(MAX_LENGTH);
    if (fgets(cmdbuffer, MAX_LENGTH, fp)) {
        break;
    }

    hp->cmd = strtok(cmdbuffer, ":");
    hp->value = strtok(0, ":");
    hp->delay = atoi(strtok(0, ":"));
    hp->next = malloc(sizeof(node_t));
    hp = hp->next;
}

if (hp->next) {
    // careful here you need to free before assigning NULL
    // or you leak memory
    free(hp->next);
    hp->next = NULL;
}

// ...

node_t *tmp;
hp = head;

while (hp) {
    tmp = hp;
    hp = hp->next;
    free(tmp->cmd);
    free(tmp);
}

Anyway, do not cast the return value of malloc().